xref: /openbsd-src/regress/usr.sbin/rpki-client/test-http.c (revision 268bb8d70cd9649707e0f844df28c7b476d480f5)
1 #include <sys/queue.h>
2 #include <sys/socket.h>
3 #include <err.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <limits.h>
7 #include <stdarg.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 
12 #include <imsg.h>
13 
14 #include "extern.h"
15 
16 static struct msgbuf	*httpq;
17 
18 void
19 logx(const char *fmt, ...)
20 {
21 	va_list ap;
22 
23 	va_start(ap, fmt);
24 	vwarnx(fmt, ap);
25 	va_end(ap);
26 }
27 
28 time_t
29 getmonotime(void)
30 {
31 	struct timespec ts;
32 
33 	if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
34 		err(1, "clock_gettime");
35 	return (ts.tv_sec);
36 }
37 
38 int
39 valid_origin(const char *uri, const char *proto)
40 {
41 	const char *to;
42 
43 	/* extract end of host from proto URI */
44 	to = strstr(proto, "://");
45 	if (to == NULL)
46 		return 0;
47 	to += strlen("://");
48 	if ((to = strchr(to, '/')) == NULL)
49 		return 0;
50 
51 	/* compare hosts including the / for the start of the path section */
52 	if (strncasecmp(uri, proto, to - proto + 1) != 0)
53 		return 0;
54 
55 	return 1;
56 }
57 
58 static void
59 http_request(unsigned int id, const char *uri, const char *last_mod, int fd)
60 {
61 	struct ibuf     *b;
62 
63 	b = io_new_buffer();
64 	io_simple_buffer(b, &id, sizeof(id));
65 	io_str_buffer(b, uri);
66 	io_str_buffer(b, last_mod);
67 	/* pass file as fd */
68 	b->fd = fd;
69 	io_close_buffer(httpq, b);
70 }
71 
72 static const char *
73 http_result(enum http_result res)
74 {
75 	switch (res) {
76 	case HTTP_OK:
77 		return "OK";
78 	case HTTP_NOT_MOD:
79 		return "not modified";
80 	case HTTP_FAILED:
81 		return "failed";
82 	default:
83 		errx(1, "unknown http result: %d", res);
84 	}
85 }
86 
87 static int
88 http_response(int fd)
89 {
90 	struct ibuf *b;
91 	unsigned int id;
92 	enum http_result res;
93 	char *lastmod;
94 
95 	while (1) {
96 		switch (msgbuf_read(fd, httpq)) {
97 		case -1:
98 			err(1, "msgbuf_read");
99 		case 0:
100 			errx(1, "msgbuf_read: connection closed");
101 		}
102 		if ((b = io_buf_get(httpq)) != NULL)
103 			break;
104 	}
105 
106 	io_read_buf(b, &id, sizeof(id));
107 	io_read_buf(b, &res, sizeof(res));
108 	io_read_str(b, &lastmod);
109 	ibuf_free(b);
110 
111 	printf("transfer %s", http_result(res));
112 	if (lastmod)
113 		printf(", last-modified: %s" , lastmod);
114 	printf("\n");
115 	return res == HTTP_FAILED;
116 }
117 
118 int
119 main(int argc, char **argv)
120 {
121 	pid_t httppid;
122 	int error, fd[2], outfd, httpfd;
123 	int fl = SOCK_STREAM | SOCK_CLOEXEC;
124 	char *uri, *file, *mod;
125 	unsigned int req = 0;
126 
127 	if (argc != 3 && argc != 4) {
128 		fprintf(stderr, "usage: test-http uri file [last-modified]\n");
129 		return 1;
130 	}
131 	uri = argv[1];
132 	file = argv[2];
133 	mod = argv[3];
134 
135 	if (socketpair(AF_UNIX, fl, 0, fd) == -1)
136 		err(1, "socketpair");
137 
138 	if ((httppid = fork()) == -1)
139 		err(1, "fork");
140 
141 	if (httppid == 0) {
142 		close(fd[1]);
143 
144 		if (pledge("stdio rpath inet dns recvfd", NULL) == -1)
145 			err(1, "pledge");
146 
147 		proc_http(NULL, fd[0]);
148 		errx(1, "http process returned");
149 	}
150 
151 	close(fd[0]);
152 	httpfd = fd[1];
153 	if ((httpq = msgbuf_new_reader(sizeof(size_t), io_parse_hdr, NULL)) ==
154 	    NULL)
155 		err(1, NULL);
156 
157 	if ((outfd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1)
158 		err(1, "open %s", file);
159 
160 	http_request(req++, uri, mod, outfd);
161 	if (msgbuf_write(httpfd, httpq) == -1)
162 		err(1, "write");
163 	error = http_response(httpfd);
164 	return error;
165 }
166