Blame


1 8d1b399b 2021-07-22 op /*
2 8d1b399b 2021-07-22 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 8d1b399b 2021-07-22 op *
4 8d1b399b 2021-07-22 op * Permission to use, copy, modify, and distribute this software for any
5 8d1b399b 2021-07-22 op * purpose with or without fee is hereby granted, provided that the above
6 8d1b399b 2021-07-22 op * copyright notice and this permission notice appear in all copies.
7 8d1b399b 2021-07-22 op *
8 8d1b399b 2021-07-22 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 8d1b399b 2021-07-22 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 8d1b399b 2021-07-22 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 8d1b399b 2021-07-22 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 8d1b399b 2021-07-22 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 8d1b399b 2021-07-22 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 8d1b399b 2021-07-22 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 8d1b399b 2021-07-22 op */
16 8d1b399b 2021-07-22 op
17 8d1b399b 2021-07-22 op #include "compat.h"
18 8d1b399b 2021-07-22 op
19 23e03c88 2021-07-26 op #include <endian.h>
20 8d1b399b 2021-07-22 op #include <errno.h>
21 8d1b399b 2021-07-22 op #include <pwd.h>
22 8d1b399b 2021-07-22 op #include <signal.h>
23 8d1b399b 2021-07-22 op #include <stdlib.h>
24 8d1b399b 2021-07-22 op #include <string.h>
25 8d1b399b 2021-07-22 op #include <syslog.h>
26 8d1b399b 2021-07-22 op #include <unistd.h>
27 8d1b399b 2021-07-22 op
28 8d1b399b 2021-07-22 op #include "client.h"
29 8d1b399b 2021-07-22 op #include "kamid.h"
30 8d1b399b 2021-07-22 op #include "log.h"
31 8d1b399b 2021-07-22 op #include "sandbox.h"
32 23e03c88 2021-07-26 op #include "utils.h"
33 8d1b399b 2021-07-22 op
34 8d1b399b 2021-07-22 op static struct imsgev *iev_listener;
35 8d1b399b 2021-07-22 op
36 06a84967 2021-07-22 op static ATTR_DEAD void client_shutdown(void);
37 8d1b399b 2021-07-22 op static void client_sig_handler(int, short, void *);
38 8d1b399b 2021-07-22 op static void client_dispatch_listener(int, short, void *);
39 8d1b399b 2021-07-22 op static void client_privdrop(const char *, const char *);
40 8d1b399b 2021-07-22 op
41 8d1b399b 2021-07-22 op static int client_imsg_compose_listener(int, uint32_t,
42 8d1b399b 2021-07-22 op const void *, uint16_t);
43 8d1b399b 2021-07-22 op
44 23e03c88 2021-07-26 op static void handle_message(struct imsg *, size_t);
45 23e03c88 2021-07-26 op
46 06a84967 2021-07-22 op ATTR_DEAD void
47 8d1b399b 2021-07-22 op client(int debug, int verbose)
48 8d1b399b 2021-07-22 op {
49 8d1b399b 2021-07-22 op struct event ev_sigint, ev_sigterm;
50 8d1b399b 2021-07-22 op
51 8d1b399b 2021-07-22 op log_init(debug, LOG_DAEMON);
52 8d1b399b 2021-07-22 op log_setverbose(verbose);
53 8d1b399b 2021-07-22 op
54 8d1b399b 2021-07-22 op setproctitle("client");
55 8d1b399b 2021-07-22 op log_procinit("client");
56 8d1b399b 2021-07-22 op
57 8d1b399b 2021-07-22 op log_debug("warming up");
58 8d1b399b 2021-07-22 op
59 8d1b399b 2021-07-22 op event_init();
60 8d1b399b 2021-07-22 op
61 8d1b399b 2021-07-22 op /* Setup signal handlers */
62 8d1b399b 2021-07-22 op signal_set(&ev_sigint, SIGINT, client_sig_handler, NULL);
63 8d1b399b 2021-07-22 op signal_set(&ev_sigterm, SIGTERM, client_sig_handler, NULL);
64 8d1b399b 2021-07-22 op
65 8d1b399b 2021-07-22 op signal_add(&ev_sigint, NULL);
66 8d1b399b 2021-07-22 op signal_add(&ev_sigterm, NULL);
67 8d1b399b 2021-07-22 op
68 8d1b399b 2021-07-22 op signal(SIGPIPE, SIG_IGN);
69 8d1b399b 2021-07-22 op signal(SIGHUP, SIG_IGN);
70 8d1b399b 2021-07-22 op
71 8d1b399b 2021-07-22 op /* Setup pipe and event handler to the listener process */
72 8d1b399b 2021-07-22 op if ((iev_listener = malloc(sizeof(*iev_listener))) == NULL)
73 8d1b399b 2021-07-22 op fatal(NULL);
74 8d1b399b 2021-07-22 op
75 8d1b399b 2021-07-22 op imsg_init(&iev_listener->ibuf, 3);
76 8d1b399b 2021-07-22 op iev_listener->handler = client_dispatch_listener;
77 8d1b399b 2021-07-22 op
78 8d1b399b 2021-07-22 op /* Setup event handlers. */
79 8d1b399b 2021-07-22 op iev_listener->events = EV_READ;
80 8d1b399b 2021-07-22 op event_set(&iev_listener->ev, iev_listener->ibuf.fd,
81 8d1b399b 2021-07-22 op iev_listener->events, iev_listener->handler, iev_listener);
82 8d1b399b 2021-07-22 op event_add(&iev_listener->ev, NULL);
83 8d1b399b 2021-07-22 op
84 8d1b399b 2021-07-22 op event_dispatch();
85 8d1b399b 2021-07-22 op client_shutdown();
86 8d1b399b 2021-07-22 op }
87 8d1b399b 2021-07-22 op
88 06a84967 2021-07-22 op static ATTR_DEAD void
89 8d1b399b 2021-07-22 op client_shutdown(void)
90 8d1b399b 2021-07-22 op {
91 8d1b399b 2021-07-22 op msgbuf_clear(&iev_listener->ibuf.w);
92 8d1b399b 2021-07-22 op close(iev_listener->ibuf.fd);
93 8d1b399b 2021-07-22 op
94 8d1b399b 2021-07-22 op free(iev_listener);
95 8d1b399b 2021-07-22 op
96 8d1b399b 2021-07-22 op log_info("client exiting");
97 8d1b399b 2021-07-22 op exit(0);
98 8d1b399b 2021-07-22 op }
99 8d1b399b 2021-07-22 op
100 8d1b399b 2021-07-22 op static void
101 8d1b399b 2021-07-22 op client_sig_handler(int sig, short event, void *d)
102 8d1b399b 2021-07-22 op {
103 8d1b399b 2021-07-22 op /*
104 8d1b399b 2021-07-22 op * Normal signal handler rules don't apply because libevent
105 8d1b399b 2021-07-22 op * decouples for us.
106 8d1b399b 2021-07-22 op */
107 8d1b399b 2021-07-22 op
108 8d1b399b 2021-07-22 op switch (sig) {
109 8d1b399b 2021-07-22 op case SIGINT:
110 8d1b399b 2021-07-22 op case SIGTERM:
111 8d1b399b 2021-07-22 op client_shutdown();
112 8d1b399b 2021-07-22 op default:
113 8d1b399b 2021-07-22 op fatalx("unexpected signal %d", sig);
114 8d1b399b 2021-07-22 op }
115 8d1b399b 2021-07-22 op }
116 8d1b399b 2021-07-22 op
117 8d1b399b 2021-07-22 op #define AUTH_NONE 0
118 8d1b399b 2021-07-22 op #define AUTH_USER 1
119 8d1b399b 2021-07-22 op #define AUTH_DONE 2
120 8d1b399b 2021-07-22 op
121 8d1b399b 2021-07-22 op static void
122 8d1b399b 2021-07-22 op client_dispatch_listener(int fd, short event, void *d)
123 8d1b399b 2021-07-22 op {
124 8d1b399b 2021-07-22 op static int auth = AUTH_NONE;
125 8d1b399b 2021-07-22 op static char username[64] = {0};
126 8d1b399b 2021-07-22 op static char dir[PATH_MAX] = {0};
127 8d1b399b 2021-07-22 op struct imsg imsg;
128 8d1b399b 2021-07-22 op struct imsgev *iev = d;
129 8d1b399b 2021-07-22 op struct imsgbuf *ibuf;
130 8d1b399b 2021-07-22 op ssize_t n;
131 8d1b399b 2021-07-22 op int shut = 0;
132 8d1b399b 2021-07-22 op
133 8d1b399b 2021-07-22 op ibuf = &iev->ibuf;
134 8d1b399b 2021-07-22 op
135 8d1b399b 2021-07-22 op if (event & EV_READ) {
136 8d1b399b 2021-07-22 op if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
137 8d1b399b 2021-07-22 op fatal("imsg_read error");
138 8d1b399b 2021-07-22 op if (n == 0) /* Connection closed */
139 8d1b399b 2021-07-22 op shut = 1;
140 8d1b399b 2021-07-22 op }
141 8d1b399b 2021-07-22 op if (event & EV_WRITE) {
142 8d1b399b 2021-07-22 op if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
143 8d1b399b 2021-07-22 op fatal("msgbuf_write");
144 8d1b399b 2021-07-22 op if (n == 0) /* Connection closed */
145 8d1b399b 2021-07-22 op shut = 1;
146 8d1b399b 2021-07-22 op }
147 8d1b399b 2021-07-22 op
148 8d1b399b 2021-07-22 op for (;;) {
149 8d1b399b 2021-07-22 op if ((n = imsg_get(ibuf, &imsg)) == -1)
150 8d1b399b 2021-07-22 op fatal("%s: imsg_get error", __func__);
151 8d1b399b 2021-07-22 op if (n == 0) /* No more messages. */
152 8d1b399b 2021-07-22 op break;
153 8d1b399b 2021-07-22 op
154 8d1b399b 2021-07-22 op switch (imsg.hdr.type) {
155 8d1b399b 2021-07-22 op case IMSG_AUTH:
156 8d1b399b 2021-07-22 op if (auth)
157 8d1b399b 2021-07-22 op fatalx("%s: IMSG_AUTH already done", __func__);
158 8d1b399b 2021-07-22 op auth = AUTH_USER;
159 8d1b399b 2021-07-22 op ((char *)imsg.data)[IMSG_DATA_SIZE(imsg)-1] = '\0';
160 8d1b399b 2021-07-22 op strlcpy(username, imsg.data, sizeof(username));
161 8d1b399b 2021-07-22 op break;
162 8d1b399b 2021-07-22 op case IMSG_AUTH_DIR:
163 8d1b399b 2021-07-22 op if (auth != AUTH_USER)
164 8d1b399b 2021-07-22 op fatalx("%s: IMSG_AUTH_DIR not after IMSG_AUTH",
165 8d1b399b 2021-07-22 op __func__);
166 8d1b399b 2021-07-22 op auth = AUTH_DONE;
167 8d1b399b 2021-07-22 op ((char *)imsg.data)[IMSG_DATA_SIZE(imsg)-1] = '\0';
168 8d1b399b 2021-07-22 op strlcpy(dir, imsg.data, sizeof(dir));
169 8d1b399b 2021-07-22 op client_privdrop(username, dir);
170 8d1b399b 2021-07-22 op memset(username, 0, sizeof(username));
171 8d1b399b 2021-07-22 op memset(dir, 0, sizeof(username));
172 8d1b399b 2021-07-22 op break;
173 8d1b399b 2021-07-22 op case IMSG_BUF:
174 8d1b399b 2021-07-22 op /* echo! */
175 23e03c88 2021-07-26 op if (!auth)
176 23e03c88 2021-07-26 op fatalx("%s: can't handle messages before"
177 23e03c88 2021-07-26 op " doing the auth", __func__);
178 23e03c88 2021-07-26 op handle_message(&imsg, IMSG_DATA_SIZE(imsg));
179 8d1b399b 2021-07-22 op break;
180 8d1b399b 2021-07-22 op case IMSG_CONN_GONE:
181 8d1b399b 2021-07-22 op log_debug("closing");
182 8d1b399b 2021-07-22 op shut = 1;
183 8d1b399b 2021-07-22 op break;
184 8d1b399b 2021-07-22 op default:
185 8d1b399b 2021-07-22 op log_debug("%s: unexpected imsg %d",
186 8d1b399b 2021-07-22 op __func__, imsg.hdr.type);
187 8d1b399b 2021-07-22 op break;
188 8d1b399b 2021-07-22 op }
189 8d1b399b 2021-07-22 op imsg_free(&imsg);
190 8d1b399b 2021-07-22 op }
191 8d1b399b 2021-07-22 op
192 8d1b399b 2021-07-22 op if (!shut)
193 8d1b399b 2021-07-22 op imsg_event_add(iev);
194 8d1b399b 2021-07-22 op else {
195 8d1b399b 2021-07-22 op /* This pipe is dead. Remove its event handler. */
196 8d1b399b 2021-07-22 op event_del(&iev->ev);
197 8d1b399b 2021-07-22 op log_warnx("pipe closed, shutting down...");
198 8d1b399b 2021-07-22 op event_loopexit(NULL);
199 8d1b399b 2021-07-22 op }
200 8d1b399b 2021-07-22 op }
201 8d1b399b 2021-07-22 op
202 8d1b399b 2021-07-22 op static void
203 8d1b399b 2021-07-22 op client_privdrop(const char *username, const char *dir)
204 8d1b399b 2021-07-22 op {
205 8d1b399b 2021-07-22 op struct passwd *pw;
206 8d1b399b 2021-07-22 op
207 8d1b399b 2021-07-22 op setproctitle("client %s", username);
208 8d1b399b 2021-07-22 op
209 8d1b399b 2021-07-22 op if ((pw = getpwnam(username)) == NULL)
210 8d1b399b 2021-07-22 op fatalx("getpwnam(%s) failed", username);
211 8d1b399b 2021-07-22 op
212 8d1b399b 2021-07-22 op if (chroot(dir) == -1)
213 8d1b399b 2021-07-22 op fatal("chroot");
214 8d1b399b 2021-07-22 op if (chdir("/") == -1)
215 8d1b399b 2021-07-22 op fatal("chdir(\"/\")");
216 8d1b399b 2021-07-22 op
217 8d1b399b 2021-07-22 op if (setgroups(1, &pw->pw_gid) ||
218 8d1b399b 2021-07-22 op setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
219 8d1b399b 2021-07-22 op setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
220 8d1b399b 2021-07-22 op fatal("can't drop privileges");
221 8d1b399b 2021-07-22 op
222 8d1b399b 2021-07-22 op sandbox_client();
223 8d1b399b 2021-07-22 op log_debug("client ready");
224 8d1b399b 2021-07-22 op }
225 8d1b399b 2021-07-22 op
226 8d1b399b 2021-07-22 op static int
227 8d1b399b 2021-07-22 op client_imsg_compose_listener(int type, uint32_t peerid,
228 8d1b399b 2021-07-22 op const void *data, uint16_t len)
229 8d1b399b 2021-07-22 op {
230 8d1b399b 2021-07-22 op int ret;
231 8d1b399b 2021-07-22 op
232 8d1b399b 2021-07-22 op if ((ret = imsg_compose(&iev_listener->ibuf, type, peerid, 0, -1,
233 8d1b399b 2021-07-22 op data, len)) != -1)
234 8d1b399b 2021-07-22 op imsg_event_add(iev_listener);
235 8d1b399b 2021-07-22 op
236 8d1b399b 2021-07-22 op return ret;
237 23e03c88 2021-07-26 op }
238 23e03c88 2021-07-26 op
239 23e03c88 2021-07-26 op static inline void
240 23e03c88 2021-07-26 op parse_message(void *data, size_t len, struct np_msg_header *hdr, void **cnt)
241 23e03c88 2021-07-26 op {
242 23e03c88 2021-07-26 op if (len < 4)
243 23e03c88 2021-07-26 op goto err;
244 23e03c88 2021-07-26 op
245 12c6d699 2021-07-26 op memcpy(hdr, data, sizeof(*hdr));
246 12c6d699 2021-07-26 op
247 23e03c88 2021-07-26 op hdr->len = le32toh(hdr->len);
248 23e03c88 2021-07-26 op
249 23e03c88 2021-07-26 op if (len != hdr->len)
250 23e03c88 2021-07-26 op goto err;
251 23e03c88 2021-07-26 op
252 23e03c88 2021-07-26 op /* type is one byte long, no endianness issues */
253 23e03c88 2021-07-26 op if (hdr->type < Tversion ||
254 23e03c88 2021-07-26 op hdr->type >= Tmax ||
255 23e03c88 2021-07-26 op hdr->type == Terror ||
256 23e03c88 2021-07-26 op (hdr->type & 0x1) != 0) /* cannot recv a R* */
257 23e03c88 2021-07-26 op goto err;
258 23e03c88 2021-07-26 op
259 23e03c88 2021-07-26 op hdr->tag = le32toh(hdr->tag);
260 23e03c88 2021-07-26 op
261 23e03c88 2021-07-26 op *cnt = data + sizeof(*hdr);
262 23e03c88 2021-07-26 op return;
263 23e03c88 2021-07-26 op
264 23e03c88 2021-07-26 op err:
265 23e03c88 2021-07-26 op /* TODO: send a proper message to terminate the connection. */
266 23e03c88 2021-07-26 op fatalx("got invalid message");
267 8d1b399b 2021-07-22 op }
268 23e03c88 2021-07-26 op
269 23e03c88 2021-07-26 op static void
270 23e03c88 2021-07-26 op handle_message(struct imsg *imsg, size_t len)
271 23e03c88 2021-07-26 op {
272 23e03c88 2021-07-26 op struct np_msg_header hdr, h;
273 23e03c88 2021-07-26 op uint32_t l;
274 23e03c88 2021-07-26 op void *data;
275 23e03c88 2021-07-26 op const char *ns_err = "Not supported.";
276 23e03c88 2021-07-26 op
277 23e03c88 2021-07-26 op parse_message(imsg->data, len, &hdr, &data);
278 23e03c88 2021-07-26 op
279 23e03c88 2021-07-26 op /* for now, log the request and reply with an error. */
280 23e03c88 2021-07-26 op
281 23e03c88 2021-07-26 op log_debug("got request type %s", pp_msg_type(hdr.type));
282 23e03c88 2021-07-26 op
283 23e03c88 2021-07-26 op memset(&h, 0, sizeof(h));
284 23e03c88 2021-07-26 op l = strlen(ns_err);
285 23e03c88 2021-07-26 op h.len = htole32(sizeof(h) + 2 + l);
286 23e03c88 2021-07-26 op h.type = Rerror;
287 23e03c88 2021-07-26 op h.tag = htole32(hdr.tag);
288 23e03c88 2021-07-26 op
289 23e03c88 2021-07-26 op client_imsg_compose_listener(IMSG_BUF, imsg->hdr.peerid,
290 23e03c88 2021-07-26 op &h, sizeof(h));
291 23e03c88 2021-07-26 op client_imsg_compose_listener(IMSG_BUF, imsg->hdr.peerid,
292 23e03c88 2021-07-26 op &l, sizeof(l));
293 23e03c88 2021-07-26 op client_imsg_compose_listener(IMSG_BUF, imsg->hdr.peerid,
294 23e03c88 2021-07-26 op ns_err, l);
295 23e03c88 2021-07-26 op }