author | Sunil Nimmagadda <sunil@nimmagadda.net> |
Tue, 06 Dec 2022 13:51:55 +0000 | |
changeset 0 | 1d0ce1ebbc72 |
permissions | -rw-r--r-- |
0
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
1 |
/* |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
2 |
* Copyright (c) 2015 Sunil Nimmagadda <sunil@openbsd.org> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
3 |
* Copyright (c) 2012 - 2015 Reyk Floeter <reyk@openbsd.org> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
4 |
* |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
5 |
* Permission to use, copy, modify, and distribute this software for any |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
6 |
* purpose with or without fee is hereby granted, provided that the above |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
7 |
* copyright notice and this permission notice appear in all copies. |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
8 |
* |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
9 |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
10 |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
11 |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
12 |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
13 |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
14 |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
15 |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
16 |
*/ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
17 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
18 |
#include <err.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
19 |
#include <fcntl.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
20 |
#include <libgen.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
21 |
#include <limits.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
22 |
#include <stdio.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
23 |
#include <stdint.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
24 |
#include <stdlib.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
25 |
#include <string.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
26 |
#include <strings.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
27 |
#include <unistd.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
28 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
29 |
#include <tls.h> |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
30 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
31 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
32 |
#include "ftp.h" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
33 |
#include "xmalloc.h" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
34 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
35 |
#define MAX_REDIRECTS 10 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
36 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
37 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
38 |
#define MINBUF 128 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
39 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
40 |
static struct tls_config *tls_config; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
41 |
static struct tls *ctx; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
42 |
static int tls_session_fd = -1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
43 |
static char * const tls_verify_opts[] = { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
44 |
#define HTTP_TLS_CAFILE 0 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
45 |
"cafile", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
46 |
#define HTTP_TLS_CAPATH 1 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
47 |
"capath", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
48 |
#define HTTP_TLS_CIPHERS 2 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
49 |
"ciphers", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
50 |
#define HTTP_TLS_DONTVERIFY 3 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
51 |
"dont", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
52 |
#define HTTP_TLS_VERIFYDEPTH 4 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
53 |
"depth", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
54 |
#define HTTP_TLS_MUSTSTAPLE 5 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
55 |
"muststaple", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
56 |
#define HTTP_TLS_NOVERIFYTIME 6 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
57 |
"noverifytime", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
58 |
#define HTTP_TLS_SESSION 7 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
59 |
"session", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
60 |
#define HTTP_TLS_DOVERIFY 8 |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
61 |
"do", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
62 |
NULL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
63 |
}; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
64 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
65 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
66 |
/* |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
67 |
* HTTP status codes based on IANA assignments (2014-06-11 version): |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
68 |
* https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
69 |
* plus legacy (306) and non-standard (420). |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
70 |
*/ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
71 |
static struct http_status { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
72 |
int code; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
73 |
const char *name; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
74 |
} http_status[] = { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
75 |
{ 100, "Continue" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
76 |
{ 101, "Switching Protocols" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
77 |
{ 102, "Processing" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
78 |
/* 103-199 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
79 |
{ 200, "OK" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
80 |
{ 201, "Created" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
81 |
{ 202, "Accepted" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
82 |
{ 203, "Non-Authoritative Information" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
83 |
{ 204, "No Content" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
84 |
{ 205, "Reset Content" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
85 |
{ 206, "Partial Content" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
86 |
{ 207, "Multi-Status" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
87 |
{ 208, "Already Reported" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
88 |
/* 209-225 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
89 |
{ 226, "IM Used" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
90 |
/* 227-299 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
91 |
{ 300, "Multiple Choices" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
92 |
{ 301, "Moved Permanently" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
93 |
{ 302, "Found" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
94 |
{ 303, "See Other" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
95 |
{ 304, "Not Modified" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
96 |
{ 305, "Use Proxy" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
97 |
{ 306, "Switch Proxy" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
98 |
{ 307, "Temporary Redirect" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
99 |
{ 308, "Permanent Redirect" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
100 |
/* 309-399 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
101 |
{ 400, "Bad Request" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
102 |
{ 401, "Unauthorized" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
103 |
{ 402, "Payment Required" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
104 |
{ 403, "Forbidden" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
105 |
{ 404, "Not Found" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
106 |
{ 405, "Method Not Allowed" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
107 |
{ 406, "Not Acceptable" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
108 |
{ 407, "Proxy Authentication Required" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
109 |
{ 408, "Request Timeout" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
110 |
{ 409, "Conflict" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
111 |
{ 410, "Gone" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
112 |
{ 411, "Length Required" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
113 |
{ 412, "Precondition Failed" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
114 |
{ 413, "Payload Too Large" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
115 |
{ 414, "URI Too Long" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
116 |
{ 415, "Unsupported Media Type" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
117 |
{ 416, "Range Not Satisfiable" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
118 |
{ 417, "Expectation Failed" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
119 |
{ 418, "I'm a teapot" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
120 |
/* 419-421 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
121 |
{ 420, "Enhance Your Calm" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
122 |
{ 422, "Unprocessable Entity" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
123 |
{ 423, "Locked" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
124 |
{ 424, "Failed Dependency" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
125 |
/* 425 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
126 |
{ 426, "Upgrade Required" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
127 |
/* 427 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
128 |
{ 428, "Precondition Required" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
129 |
{ 429, "Too Many Requests" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
130 |
/* 430 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
131 |
{ 431, "Request Header Fields Too Large" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
132 |
/* 432-450 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
133 |
{ 451, "Unavailable For Legal Reasons" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
134 |
/* 452-499 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
135 |
{ 500, "Internal Server Error" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
136 |
{ 501, "Not Implemented" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
137 |
{ 502, "Bad Gateway" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
138 |
{ 503, "Service Unavailable" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
139 |
{ 504, "Gateway Timeout" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
140 |
{ 505, "HTTP Version Not Supported" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
141 |
{ 506, "Variant Also Negotiates" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
142 |
{ 507, "Insufficient Storage" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
143 |
{ 508, "Loop Detected" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
144 |
/* 509 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
145 |
{ 510, "Not Extended" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
146 |
{ 511, "Network Authentication Required" }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
147 |
/* 512-599 unassigned */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
148 |
{ 0, NULL }, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
149 |
}; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
150 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
151 |
struct http_headers { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
152 |
char *location; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
153 |
off_t content_length; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
154 |
int chunked; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
155 |
int retry_after; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
156 |
}; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
157 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
158 |
static void decode_chunk(int, uint, FILE *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
159 |
static char *header_lookup(const char *, const char *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
160 |
static const char *http_error(int); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
161 |
static int http_status_cmp(const void *, const void *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
162 |
static void http_headers_free(struct http_headers *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
163 |
static ssize_t http_getline(int, char **, size_t *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
164 |
static void http_proxy_connect(struct url *, struct url *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
165 |
static char *http_prepare_request(struct url *, off_t *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
166 |
static size_t http_read(int, char *, size_t); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
167 |
static struct url *http_redirect(struct url *, char *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
168 |
static void http_copy_chunks(struct url *, FILE *, off_t *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
169 |
static int http_request(int, const char *, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
170 |
struct http_headers **); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
171 |
static char *relative_path_resolve(const char *, const char *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
172 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
173 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
174 |
static void tls_copy_file(struct url *, FILE *, off_t *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
175 |
static ssize_t tls_getline(char **, size_t *, struct tls *); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
176 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
177 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
178 |
static FILE *fp; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
179 |
static int chunked; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
180 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
181 |
void |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
182 |
http_connect(struct url *url, int timeout) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
183 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
184 |
static struct url *proxy; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
185 |
const char *host, *port; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
186 |
int sock; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
187 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
188 |
proxy = (url->scheme == S_HTTPS || url->scheme == S_HTTP) ? |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
189 |
http_proxy : ftp_proxy; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
190 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
191 |
host = proxy ? proxy->host : url->host; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
192 |
port = proxy ? proxy->port : url->port; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
193 |
if ((sock = tcp_connect(host, port, timeout)) == -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
194 |
exit(1); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
195 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
196 |
if ((fp = fdopen(sock, "r+")) == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
197 |
err(1, "%s: fdopen", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
198 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
199 |
if (proxy) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
200 |
http_proxy_connect(proxy, url); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
201 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
202 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
203 |
if (url->scheme != S_HTTPS) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
204 |
return; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
205 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
206 |
if ((ctx = tls_client()) == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
207 |
errx(1, "failed to create tls client"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
208 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
209 |
if (tls_configure(ctx, tls_config) != 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
210 |
errx(1, "%s: %s", __func__, tls_error(ctx)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
211 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
212 |
if (tls_connect_socket(ctx, fileno(fp), url->host) != 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
213 |
errx(1, "%s: %s", __func__, tls_error(ctx)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
214 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
215 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
216 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
217 |
static void |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
218 |
http_proxy_connect(struct url *proxy, struct url *url) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
219 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
220 |
struct http_headers *headers; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
221 |
char *auth = NULL, *req; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
222 |
int authlen = 0, code; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
223 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
224 |
if (proxy->basic_auth) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
225 |
authlen = xasprintf(&auth, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
226 |
"Proxy-Authorization: Basic %s\r\n", proxy->basic_auth); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
227 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
228 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
229 |
xasprintf(&req, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
230 |
"CONNECT %s:%s HTTP/1.0\r\n" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
231 |
"User-Agent: %s\r\n" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
232 |
"%s" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
233 |
"\r\n", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
234 |
url->host, url->port, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
235 |
useragent, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
236 |
proxy->basic_auth ? auth : ""); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
237 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
238 |
freezero(auth, authlen); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
239 |
if ((code = http_request(S_HTTP, req, &headers)) != 200) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
240 |
errx(1, "%s: Failed to CONNECT to %s:%s: %d %s", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
241 |
__func__, url->host, url->port, code, http_error(code)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
242 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
243 |
free(req); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
244 |
http_headers_free(headers); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
245 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
246 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
247 |
static char * |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
248 |
http_prepare_request(struct url *url, off_t *offset) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
249 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
250 |
char *auth = NULL, *path = NULL, *range = NULL, *req; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
251 |
int authlen = 0; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
252 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
253 |
if (*offset) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
254 |
xasprintf(&range, "Range: bytes=%lld-\r\n", *offset); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
255 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
256 |
if (url->basic_auth) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
257 |
authlen = xasprintf(&auth, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
258 |
"Authorization: Basic %s\r\n", url->basic_auth); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
259 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
260 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
261 |
if (url->path) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
262 |
path = url_encode(url->path); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
263 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
264 |
xasprintf(&req, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
265 |
"GET %s HTTP/1.1\r\n" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
266 |
"Host: %s\r\n" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
267 |
"%s" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
268 |
"%s" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
269 |
"Connection: close\r\n" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
270 |
"User-Agent: %s\r\n" |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
271 |
"\r\n", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
272 |
path ? path : "/", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
273 |
url->host, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
274 |
*offset ? range : "", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
275 |
url->basic_auth ? auth : "", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
276 |
useragent); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
277 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
278 |
free(range); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
279 |
freezero(auth, authlen); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
280 |
free(path); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
281 |
return req; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
282 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
283 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
284 |
struct url * |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
285 |
http_get(struct url *url, off_t *offset, off_t *sz) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
286 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
287 |
struct http_headers *headers; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
288 |
char *req; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
289 |
int code, redirects = 0, retry = 0; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
290 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
291 |
do { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
292 |
log_request("Requesting", url, http_proxy); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
293 |
req = http_prepare_request(url, offset); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
294 |
code = http_request(url->scheme, req, &headers); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
295 |
free(req); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
296 |
switch (code) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
297 |
case 200: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
298 |
if (*offset) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
299 |
warnx("Server does not support resume."); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
300 |
*offset = 0; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
301 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
302 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
303 |
case 206: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
304 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
305 |
case 301: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
306 |
case 302: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
307 |
case 303: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
308 |
case 307: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
309 |
http_close(url); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
310 |
if (++redirects > MAX_REDIRECTS) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
311 |
errx(1, "Too many redirections requested."); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
312 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
313 |
if (headers->location == NULL) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
314 |
errx(1, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
315 |
"%s: Location header missing", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
316 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
317 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
318 |
url = http_redirect(url, headers->location); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
319 |
http_headers_free(headers); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
320 |
log_request("Redirected to", url, http_proxy); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
321 |
http_connect(url, 0); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
322 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
323 |
case 416: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
324 |
errx(1, "File is already fully retrieved."); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
325 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
326 |
case 503: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
327 |
if (headers->retry_after == 0 && retry == 0) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
328 |
http_close(url); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
329 |
http_headers_free(headers); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
330 |
retry = 1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
331 |
log_request("Retrying", url, http_proxy); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
332 |
http_connect(url, 0); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
333 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
334 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
335 |
/* FALLTHROUGH */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
336 |
default: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
337 |
errx(1, "Error retrieving file: %d %s", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
338 |
code, http_error(code)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
339 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
340 |
} while (code == 301 || code == 302 || |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
341 |
code == 303 || code == 307 || code == 503); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
342 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
343 |
*sz = headers->content_length + *offset; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
344 |
chunked = headers->chunked; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
345 |
http_headers_free(headers); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
346 |
return url; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
347 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
348 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
349 |
void |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
350 |
http_save(struct url *url, FILE *dst_fp, off_t *offset) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
351 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
352 |
if (chunked) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
353 |
http_copy_chunks(url, dst_fp, offset); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
354 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
355 |
else if (url->scheme == S_HTTPS) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
356 |
tls_copy_file(url, dst_fp, offset); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
357 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
358 |
else |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
359 |
copy_file(dst_fp, fp, offset); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
360 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
361 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
362 |
static struct url * |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
363 |
http_redirect(struct url *old_url, char *location) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
364 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
365 |
struct url *new_url; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
366 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
367 |
/* absolute uri reference */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
368 |
if (strncasecmp(location, "http", 4) == 0 || |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
369 |
strncasecmp(location, "https", 5) == 0) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
370 |
new_url = xurl_parse(location); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
371 |
goto done; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
372 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
373 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
374 |
/* relative uri reference */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
375 |
new_url = xcalloc(1, sizeof *new_url); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
376 |
new_url->scheme = old_url->scheme; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
377 |
new_url->host = xstrdup(old_url->host); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
378 |
new_url->port = xstrdup(old_url->port); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
379 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
380 |
/* absolute-path reference */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
381 |
if (location[0] == '/') |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
382 |
new_url->path = xstrdup(location); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
383 |
else |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
384 |
new_url->path = relative_path_resolve(old_url->path, location); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
385 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
386 |
done: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
387 |
url_free(old_url); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
388 |
return new_url; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
389 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
390 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
391 |
static char * |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
392 |
relative_path_resolve(const char *base_path, const char *location) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
393 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
394 |
char *new_path, *p; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
395 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
396 |
/* trim fragment component from both uri */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
397 |
if ((p = strchr(location, '#')) != NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
398 |
*p = '\0'; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
399 |
if (base_path && (p = strchr(base_path, '#')) != NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
400 |
*p = '\0'; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
401 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
402 |
if (base_path == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
403 |
xasprintf(&new_path, "/%s", location); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
404 |
else if (base_path[strlen(base_path) - 1] == '/') |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
405 |
xasprintf(&new_path, "%s%s", base_path, location); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
406 |
else { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
407 |
p = dirname(base_path); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
408 |
xasprintf(&new_path, "%s/%s", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
409 |
strcmp(p, ".") == 0 ? "" : p, location); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
410 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
411 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
412 |
return new_path; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
413 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
414 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
415 |
static void |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
416 |
http_copy_chunks(struct url *url, FILE *dst_fp, off_t *offset) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
417 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
418 |
char *buf = NULL; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
419 |
size_t n = 0; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
420 |
uint chunk_sz; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
421 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
422 |
http_getline(url->scheme, &buf, &n); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
423 |
if (sscanf(buf, "%x", &chunk_sz) != 1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
424 |
errx(1, "%s: Failed to get chunk size", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
425 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
426 |
while (chunk_sz > 0) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
427 |
decode_chunk(url->scheme, chunk_sz, dst_fp); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
428 |
*offset += chunk_sz; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
429 |
http_getline(url->scheme, &buf, &n); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
430 |
if (sscanf(buf, "%x", &chunk_sz) != 1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
431 |
errx(1, "%s: Failed to get chunk size", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
432 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
433 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
434 |
free(buf); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
435 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
436 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
437 |
static void |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
438 |
decode_chunk(int scheme, uint sz, FILE *dst_fp) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
439 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
440 |
size_t bufsz; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
441 |
size_t r; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
442 |
char buf[BUFSIZ], crlf[2]; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
443 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
444 |
bufsz = sizeof(buf); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
445 |
while (sz > 0) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
446 |
if (sz < bufsz) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
447 |
bufsz = sz; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
448 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
449 |
r = http_read(scheme, buf, bufsz); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
450 |
if (fwrite(buf, 1, r, dst_fp) != r) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
451 |
errx(1, "%s: fwrite", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
452 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
453 |
sz -= r; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
454 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
455 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
456 |
/* CRLF terminating the chunk */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
457 |
if (http_read(scheme, crlf, sizeof(crlf)) != sizeof(crlf)) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
458 |
errx(1, "%s: Failed to read terminal crlf", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
459 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
460 |
if (crlf[0] != '\r' || crlf[1] != '\n') |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
461 |
errx(1, "%s: Invalid chunked encoding", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
462 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
463 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
464 |
void |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
465 |
http_close(struct url *url) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
466 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
467 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
468 |
ssize_t r; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
469 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
470 |
if (url->scheme == S_HTTPS) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
471 |
if (tls_session_fd != -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
472 |
dprintf(STDERR_FILENO, "tls session resumed: %s\n", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
473 |
tls_conn_session_resumed(ctx) ? "yes" : "no"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
474 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
475 |
do { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
476 |
r = tls_close(ctx); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
477 |
} while (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
478 |
tls_free(ctx); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
479 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
480 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
481 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
482 |
fclose(fp); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
483 |
chunked = 0; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
484 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
485 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
486 |
static int |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
487 |
http_request(int scheme, const char *req, struct http_headers **hdrs) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
488 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
489 |
struct http_headers *headers; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
490 |
const char *e; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
491 |
char *buf = NULL, *p; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
492 |
size_t n = 0; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
493 |
ssize_t buflen; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
494 |
uint code; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
495 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
496 |
size_t len; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
497 |
ssize_t nw; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
498 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
499 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
500 |
if (io_debug) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
501 |
fprintf(stderr, "<<< %s", req); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
502 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
503 |
switch (scheme) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
504 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
505 |
case S_HTTPS: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
506 |
len = strlen(req); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
507 |
while (len > 0) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
508 |
nw = tls_write(ctx, req, len); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
509 |
if (nw == TLS_WANT_POLLIN || nw == TLS_WANT_POLLOUT) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
510 |
continue; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
511 |
if (nw < 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
512 |
errx(1, "tls_write: %s", tls_error(ctx)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
513 |
req += nw; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
514 |
len -= nw; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
515 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
516 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
517 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
518 |
case S_HTTP: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
519 |
if (fprintf(fp, "%s", req) < 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
520 |
errx(1, "%s: fprintf", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
521 |
(void)fflush(fp); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
522 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
523 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
524 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
525 |
http_getline(scheme, &buf, &n); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
526 |
if (io_debug) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
527 |
fprintf(stderr, ">>> %s", buf); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
528 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
529 |
if (sscanf(buf, "%*s %u %*s", &code) != 1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
530 |
errx(1, "%s: failed to extract status code", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
531 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
532 |
if (code < 100 || code > 511) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
533 |
errx(1, "%s: invalid status code %d", __func__, code); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
534 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
535 |
headers = xcalloc(1, sizeof *headers); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
536 |
headers->retry_after = -1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
537 |
for (;;) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
538 |
buflen = http_getline(scheme, &buf, &n); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
539 |
buflen -= 1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
540 |
if (buflen > 0 && buf[buflen - 1] == '\r') |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
541 |
buflen -= 1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
542 |
buf[buflen] = '\0'; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
543 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
544 |
if (io_debug) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
545 |
fprintf(stderr, ">>> %s\n", buf); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
546 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
547 |
if (buflen == 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
548 |
break; /* end of headers */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
549 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
550 |
if ((p = header_lookup(buf, "Content-Length:")) != NULL) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
551 |
headers->content_length = strtonum(p, 0, INT64_MAX, &e); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
552 |
if (e) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
553 |
err(1, "%s: Content-Length is %s: %lld", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
554 |
__func__, e, headers->content_length); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
555 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
556 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
557 |
if ((p = header_lookup(buf, "Location:")) != NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
558 |
headers->location = xstrdup(p); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
559 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
560 |
if ((p = header_lookup(buf, "Transfer-Encoding:")) != NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
561 |
if (strcasestr(p, "chunked") != NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
562 |
headers->chunked = 1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
563 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
564 |
if ((p = header_lookup(buf, "Retry-After:")) != NULL) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
565 |
headers->retry_after = strtonum(p, 0, 0, &e); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
566 |
if (e) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
567 |
headers->retry_after = -1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
568 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
569 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
570 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
571 |
*hdrs = headers; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
572 |
free(buf); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
573 |
return code; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
574 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
575 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
576 |
static void |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
577 |
http_headers_free(struct http_headers *headers) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
578 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
579 |
if (headers == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
580 |
return; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
581 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
582 |
free(headers->location); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
583 |
free(headers); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
584 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
585 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
586 |
static char * |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
587 |
header_lookup(const char *buf, const char *key) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
588 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
589 |
char *p; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
590 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
591 |
if (strncasecmp(buf, key, strlen(key)) == 0) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
592 |
if ((p = strchr(buf, ' ')) == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
593 |
errx(1, "Failed to parse %s", key); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
594 |
return ++p; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
595 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
596 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
597 |
return NULL; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
598 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
599 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
600 |
static ssize_t |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
601 |
http_getline(int scheme, char **buf, size_t *n) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
602 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
603 |
ssize_t buflen; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
604 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
605 |
switch (scheme) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
606 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
607 |
case S_HTTPS: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
608 |
if ((buflen = tls_getline(buf, n, ctx)) == -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
609 |
errx(1, "%s: tls_getline", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
610 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
611 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
612 |
case S_HTTP: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
613 |
if ((buflen = getline(buf, n, fp)) == -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
614 |
err(1, "%s: getline", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
615 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
616 |
default: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
617 |
errx(1, "%s: invalid scheme", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
618 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
619 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
620 |
return buflen; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
621 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
622 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
623 |
static size_t |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
624 |
http_read(int scheme, char *buf, size_t size) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
625 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
626 |
size_t r; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
627 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
628 |
ssize_t rs; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
629 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
630 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
631 |
switch (scheme) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
632 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
633 |
case S_HTTPS: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
634 |
do { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
635 |
rs = tls_read(ctx, buf, size); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
636 |
} while (rs == TLS_WANT_POLLIN || rs == TLS_WANT_POLLOUT); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
637 |
if (rs == -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
638 |
errx(1, "%s: tls_read: %s", __func__, tls_error(ctx)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
639 |
r = rs; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
640 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
641 |
#endif /* NOSSL */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
642 |
case S_HTTP: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
643 |
if ((r = fread(buf, 1, size, fp)) < size) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
644 |
if (!feof(fp)) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
645 |
errx(1, "%s: fread", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
646 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
647 |
default: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
648 |
errx(1, "%s: invalid scheme", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
649 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
650 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
651 |
return r; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
652 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
653 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
654 |
static const char * |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
655 |
http_error(int code) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
656 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
657 |
struct http_status error, *res; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
658 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
659 |
/* Set up key */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
660 |
error.code = code; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
661 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
662 |
if ((res = bsearch(&error, http_status, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
663 |
sizeof(http_status) / sizeof(http_status[0]) - 1, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
664 |
sizeof(http_status[0]), http_status_cmp)) != NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
665 |
return (res->name); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
666 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
667 |
return (NULL); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
668 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
669 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
670 |
static int |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
671 |
http_status_cmp(const void *a, const void *b) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
672 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
673 |
const struct http_status *ea = a; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
674 |
const struct http_status *eb = b; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
675 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
676 |
return (ea->code - eb->code); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
677 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
678 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
679 |
#ifndef NOSSL |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
680 |
void |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
681 |
https_init(char *tls_options) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
682 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
683 |
char *str; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
684 |
int depth; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
685 |
const char *ca_file, *errstr; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
686 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
687 |
if (tls_init() != 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
688 |
errx(1, "tls_init failed"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
689 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
690 |
if ((tls_config = tls_config_new()) == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
691 |
errx(1, "tls_config_new failed"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
692 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
693 |
if (tls_config_set_protocols(tls_config, TLS_PROTOCOLS_ALL) != 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
694 |
errx(1, "tls set protocols failed: %s", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
695 |
tls_config_error(tls_config)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
696 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
697 |
if (tls_config_set_ciphers(tls_config, "legacy") != 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
698 |
errx(1, "tls set ciphers failed: %s", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
699 |
tls_config_error(tls_config)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
700 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
701 |
ca_file = tls_default_ca_cert_file(); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
702 |
while (tls_options && *tls_options) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
703 |
switch (getsubopt(&tls_options, tls_verify_opts, &str)) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
704 |
case HTTP_TLS_CAFILE: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
705 |
if (str == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
706 |
errx(1, "missing CA file"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
707 |
ca_file = str; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
708 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
709 |
case HTTP_TLS_CAPATH: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
710 |
if (str == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
711 |
errx(1, "missing ca path"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
712 |
if (tls_config_set_ca_path(tls_config, str) != 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
713 |
errx(1, "tls ca path failed"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
714 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
715 |
case HTTP_TLS_CIPHERS: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
716 |
if (str == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
717 |
errx(1, "missing cipher list"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
718 |
if (tls_config_set_ciphers(tls_config, str) != 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
719 |
errx(1, "tls set ciphers failed"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
720 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
721 |
case HTTP_TLS_DONTVERIFY: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
722 |
tls_config_insecure_noverifycert(tls_config); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
723 |
tls_config_insecure_noverifyname(tls_config); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
724 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
725 |
case HTTP_TLS_VERIFYDEPTH: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
726 |
if (str == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
727 |
errx(1, "missing depth"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
728 |
depth = strtonum(str, 0, INT_MAX, &errstr); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
729 |
if (errstr) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
730 |
errx(1, "Cert validation depth is %s", errstr); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
731 |
tls_config_set_verify_depth(tls_config, depth); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
732 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
733 |
case HTTP_TLS_MUSTSTAPLE: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
734 |
tls_config_ocsp_require_stapling(tls_config); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
735 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
736 |
case HTTP_TLS_NOVERIFYTIME: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
737 |
tls_config_insecure_noverifytime(tls_config); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
738 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
739 |
case HTTP_TLS_SESSION: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
740 |
if (str == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
741 |
errx(1, "missing session file"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
742 |
tls_session_fd = open(str, O_RDWR|O_CREAT, 0600); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
743 |
if (tls_session_fd == -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
744 |
err(1, "failed to open or create session file " |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
745 |
"'%s'", str); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
746 |
if (tls_config_set_session_fd(tls_config, |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
747 |
tls_session_fd) == -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
748 |
errx(1, "failed to set session: %s", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
749 |
tls_config_error(tls_config)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
750 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
751 |
case HTTP_TLS_DOVERIFY: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
752 |
/* For compatibility, we do verify by default */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
753 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
754 |
default: |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
755 |
errx(1, "Unknown -S suboption `%s'", |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
756 |
suboptarg ? suboptarg : ""); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
757 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
758 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
759 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
760 |
if (tls_config_set_ca_file(tls_config, ca_file) == -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
761 |
errx(1, "tls_config_set_ca_file failed"); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
762 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
763 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
764 |
static ssize_t |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
765 |
tls_getline(char **buf, size_t *buflen, struct tls *tls) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
766 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
767 |
char *newb; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
768 |
size_t newlen, off; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
769 |
int ret; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
770 |
unsigned char c; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
771 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
772 |
if (buf == NULL || buflen == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
773 |
return -1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
774 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
775 |
/* If buf is NULL, we have to assume a size of zero */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
776 |
if (*buf == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
777 |
*buflen = 0; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
778 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
779 |
off = 0; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
780 |
do { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
781 |
do { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
782 |
ret = tls_read(tls, &c, 1); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
783 |
} while (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
784 |
if (ret == -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
785 |
return -1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
786 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
787 |
/* Ensure we can handle it */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
788 |
if (off + 2 > SSIZE_MAX) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
789 |
return -1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
790 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
791 |
newlen = off + 2; /* reserve space for NUL terminator */ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
792 |
if (newlen > *buflen) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
793 |
newlen = newlen < MINBUF ? MINBUF : *buflen * 2; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
794 |
newb = recallocarray(*buf, *buflen, newlen, 1); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
795 |
if (newb == NULL) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
796 |
return -1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
797 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
798 |
*buf = newb; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
799 |
*buflen = newlen; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
800 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
801 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
802 |
*(*buf + off) = c; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
803 |
off += 1; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
804 |
} while (c != '\n'); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
805 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
806 |
*(*buf + off) = '\0'; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
807 |
return off; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
808 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
809 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
810 |
static void |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
811 |
tls_copy_file(struct url *url, FILE *dst_fp, off_t *offset) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
812 |
{ |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
813 |
char *tmp_buf; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
814 |
ssize_t r; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
815 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
816 |
tmp_buf = xmalloc(TMPBUF_LEN); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
817 |
for (;;) { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
818 |
do { |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
819 |
r = tls_read(ctx, tmp_buf, TMPBUF_LEN); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
820 |
} while (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
821 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
822 |
if (r == -1) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
823 |
errx(1, "%s: tls_read: %s", __func__, tls_error(ctx)); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
824 |
else if (r == 0) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
825 |
break; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
826 |
|
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
827 |
*offset += r; |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
828 |
if (fwrite(tmp_buf, 1, r, dst_fp) != (size_t)r) |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
829 |
err(1, "%s: fwrite", __func__); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
830 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
831 |
free(tmp_buf); |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
832 |
} |
1d0ce1ebbc72
An HTTP(S), FTP client.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff
changeset
|
833 |
#endif /* NOSSL */ |