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