2 * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 #define DEBUG_PACKETS 0
39 STAILQ_HEAD(qidhead, qid) qids;
41 /* definition of a qid */
52 STAILQ_ENTRY(qid) entries;
55 STAILQ_HEAD(fidhead, fid) fids;
60 STAILQ_ENTRY(fid) entries;
63 static struct imsgev *iev_listener;
64 static struct evbuffer *evb;
65 static uint32_t peerid;
67 static int handshaked, attached;
70 static ATTR_DEAD void client_shutdown(void);
71 static void client_sig_handler(int, short, void *);
72 static void client_dispatch_listener(int, short, void *);
73 static void client_privdrop(const char *, const char *);
75 static int client_send_listener(int, const void *, uint16_t);
77 static void qid_set_from_sb(struct qid *);
78 static int qid_update_stat(struct qid *);
79 static struct qid *qid_from_copy(const struct qid *);
80 static struct qid *qid_from_fd(int);
81 static struct qid *qid_from_path(const char *);
82 static struct qid *qid_incref(struct qid *);
83 static void qid_decref(struct qid *);
85 static struct fid *new_fid(struct qid *, uint32_t);
86 static struct fid *fid_by_id(uint32_t);
87 static void free_fid(struct fid *);
89 static void parse_message(const uint8_t *, size_t,
90 struct np_msg_header *, uint8_t **);
92 static void np_write16(uint16_t);
93 static void np_header(uint32_t, uint8_t, uint16_t);
94 static void np_string(uint16_t, const char *);
95 static void np_qid(struct qid *);
96 static void do_send(void);
98 static void np_version(uint16_t, uint32_t, const char *);
99 static void np_attach(uint16_t, struct qid *);
100 static void np_clunk(uint16_t);
101 static void np_flush(uint16_t);
102 static void np_walk(uint16_t, int, struct qid *);
103 static void np_error(uint16_t, const char *);
104 static void np_errno(uint16_t);
106 static int np_read8(const char *, const char *, uint8_t *,
107 const uint8_t **, size_t *);
108 static int np_read16(const char *, const char *, uint16_t *,
109 const uint8_t **, size_t *);
110 static int np_read32(const char *, const char *, uint32_t *,
111 const uint8_t **, size_t *);
113 #define READSTRERR -1
114 #define READSTRTRUNC -2
115 static int np_readstr(const char *, const char *, char *, size_t,
116 const uint8_t **, size_t *);
118 #define NPREAD8(f, dst, src, len) np_read8(__func__, f, dst, src, len)
119 #define NPREAD16(f, dst, src, len) np_read16(__func__, f, dst, src, len)
120 #define NPREAD32(f, dst, src, len) np_read32(__func__, f, dst, src, len)
122 #define NPREADSTR(f, b, bl, src, len) np_readstr(__func__, f, b, bl, src, len)
124 static void tversion(struct np_msg_header *, const uint8_t *, size_t);
125 static void tattach(struct np_msg_header *, const uint8_t *, size_t);
126 static void tclunk(struct np_msg_header *, const uint8_t *, size_t);
127 static void tflush(struct np_msg_header *, const uint8_t *, size_t);
128 static void twalk(struct np_msg_header *, const uint8_t *, size_t);
129 static void handle_message(struct imsg *, size_t);
132 client(int debug, int verbose)
134 struct event ev_sigint, ev_sigterm;
136 log_init(debug, LOG_DAEMON);
137 log_setverbose(verbose);
139 setproctitle("client");
140 log_procinit("client");
142 log_debug("warming up");
146 /* Setup signal handlers */
147 signal_set(&ev_sigint, SIGINT, client_sig_handler, NULL);
148 signal_set(&ev_sigterm, SIGTERM, client_sig_handler, NULL);
150 signal_add(&ev_sigint, NULL);
151 signal_add(&ev_sigterm, NULL);
153 signal(SIGPIPE, SIG_IGN);
154 signal(SIGHUP, SIG_IGN);
156 /* Setup pipe and event handler to the listener process */
157 if ((iev_listener = malloc(sizeof(*iev_listener))) == NULL)
160 imsg_init(&iev_listener->ibuf, 3);
161 iev_listener->handler = client_dispatch_listener;
163 /* Setup event handlers. */
164 iev_listener->events = EV_READ;
165 event_set(&iev_listener->ev, iev_listener->ibuf.fd,
166 iev_listener->events, iev_listener->handler, iev_listener);
167 event_add(&iev_listener->ev, NULL);
173 static ATTR_DEAD void
174 client_shutdown(void)
179 msgbuf_clear(&iev_listener->ibuf.w);
180 close(iev_listener->ibuf.fd);
184 log_info("client exiting");
189 client_sig_handler(int sig, short event, void *d)
192 * Normal signal handler rules don't apply because libevent
201 fatalx("unexpected signal %d", sig);
210 client_dispatch_listener(int fd, short event, void *d)
212 static int auth = AUTH_NONE;
213 static char username[64] = {0};
214 static char dir[PATH_MAX] = {0};
216 struct imsgev *iev = d;
217 struct imsgbuf *ibuf;
223 if (event & EV_READ) {
224 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
225 fatal("imsg_read error");
226 if (n == 0) /* Connection closed */
229 if (event & EV_WRITE) {
230 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
231 fatal("msgbuf_write");
232 if (n == 0) /* Connection closed */
237 if ((n = imsg_get(ibuf, &imsg)) == -1)
238 fatal("%s: imsg_get error", __func__);
239 if (n == 0) /* No more messages. */
242 switch (imsg.hdr.type) {
244 peerid = imsg.hdr.peerid;
246 fatalx("%s: IMSG_AUTH already done", __func__);
248 ((char *)imsg.data)[IMSG_DATA_SIZE(imsg)-1] = '\0';
249 strlcpy(username, imsg.data, sizeof(username));
252 if (auth != AUTH_USER)
253 fatalx("%s: IMSG_AUTH_DIR not after IMSG_AUTH",
256 ((char *)imsg.data)[IMSG_DATA_SIZE(imsg)-1] = '\0';
257 strlcpy(dir, imsg.data, sizeof(dir));
258 client_privdrop(username, dir);
259 memset(username, 0, sizeof(username));
260 memset(dir, 0, sizeof(username));
265 fatalx("%s: can't handle messages before"
266 " doing the auth", __func__);
267 handle_message(&imsg, IMSG_DATA_SIZE(imsg));
270 log_debug("closing");
274 log_debug("%s: unexpected imsg %d",
275 __func__, imsg.hdr.type);
284 /* This pipe is dead. Remove its event handler. */
286 log_warnx("pipe closed, shutting down...");
287 event_loopexit(NULL);
292 client_privdrop(const char *username, const char *dir)
296 setproctitle("client %s", username);
298 if ((pw = getpwnam(username)) == NULL)
299 fatalx("getpwnam(%s) failed", username);
301 if (chroot(dir) == -1)
303 if (chdir("/") == -1)
304 fatal("chdir(\"/\")");
306 if (setgroups(1, &pw->pw_gid) ||
307 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
308 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
309 fatal("can't drop privileges");
312 log_debug("client ready; user=%s dir=%s", username, dir);
314 if ((evb = evbuffer_new()) == NULL)
315 fatal("evbuffer_new");
319 client_send_listener(int type, const void *data, uint16_t len)
323 if ((ret = imsg_compose(&iev_listener->ibuf, type, peerid, 0, -1,
325 imsg_event_add(iev_listener);
330 /* set qid fields from the sb field */
332 qid_set_from_sb(struct qid *qid)
334 qid->path = qid->sb.st_ino;
337 * Theoretically (and hopefully!) this should be a 64 bit
338 * number. Unfortunately, 9P uses 32 bit timestamps.
340 qid->vers = qid->sb.st_mtim.tv_sec;
342 if (S_ISREG(qid->sb.st_mode))
344 else if (S_ISDIR(qid->sb.st_mode))
346 else if (S_ISLNK(qid->sb.st_mode))
347 qid->type = QTSYMLINK;
350 /* update qid info */
352 qid_update_stat(struct qid *qid)
354 if (fstat(qid->fd, &qid->sb) == -1)
357 qid_set_from_sb(qid);
361 /* create a new qid by copying info from an existing one */
363 qid_from_copy(const struct qid *qid)
367 if ((q = calloc(1, sizeof(*q))) == NULL)
371 memcpy(q->fpath, qid->fpath, sizeof(q->fpath));
373 memcpy(&q->sb, &qid->sb, sizeof(q->sb));
374 memcpy(&q->path, &qid->path, sizeof(q->path));
375 memcpy(&q->vers, &qid->vers, sizeof(q->vers));
376 memcpy(&q->type, &qid->type, sizeof(q->type));
381 /* creates a qid given a fd */
387 if ((qid = calloc(1, sizeof(*qid))) == NULL)
391 qid_update_stat(qid);
393 STAILQ_INSERT_HEAD(&qids, qid, entries);
399 qid_from_path(const char *path)
403 if ((qid = calloc(1, sizeof(*qid))) == NULL)
408 if (stat(path, &qid->sb) == -1) {
413 qid_set_from_sb(qid);
415 STAILQ_INSERT_HEAD(&qids, qid, entries);
421 qid_incref(struct qid *qid)
428 qid_decref(struct qid *qid)
430 if (--qid->refcount > 0)
433 STAILQ_REMOVE(&qids, qid, qid, entries);
438 if (STAILQ_EMPTY(&qids))
443 new_fid(struct qid *qid, uint32_t fid)
447 if ((f = calloc(1, sizeof(*f))) == NULL)
450 f->qid = qid_incref(qid);
453 STAILQ_INSERT_HEAD(&fids, f, entries);
459 fid_by_id(uint32_t fid)
463 STAILQ_FOREACH(f, &fids, entries) {
472 free_fid(struct fid *f)
476 STAILQ_REMOVE(&fids, f, fid, entries);
481 parse_message(const uint8_t *data, size_t len, struct np_msg_header *hdr,
486 if (!NPREAD32("len", &hdr->len, &data, &len) ||
487 !NPREAD8("type", &hdr->type, &data, &len) ||
488 !NPREAD16("tag", &hdr->tag, &data, &len))
491 if (olen != hdr->len)
494 if (hdr->type < Tversion ||
496 hdr->type == Terror ||
497 (hdr->type & 0x1) != 0) /* cannot recv a R* */
500 hdr->tag = le32toh(hdr->tag);
502 *cnt = (uint8_t *)data;
506 /* TODO: send a proper message to terminate the connection. */
507 fatalx("got invalid message");
511 np_write16(uint16_t x)
514 evbuffer_add(evb, &x, sizeof(x));
518 np_header(uint32_t len, uint8_t type, uint16_t tag)
525 evbuffer_add(evb, &len, sizeof(len));
526 evbuffer_add(evb, &type, sizeof(type));
527 evbuffer_add(evb, &tag, sizeof(tag));
531 np_string(uint16_t len, const char *str)
536 evbuffer_add(evb, &len, sizeof(len));
537 evbuffer_add(evb, str, l);
541 np_qid(struct qid *qid)
546 path = htole64(qid->path);
547 vers = htole32(qid->vers);
549 evbuffer_add(evb, &qid->type, sizeof(qid->type));
550 evbuffer_add(evb, &vers, sizeof(vers));
551 evbuffer_add(evb, &path, sizeof(path));
560 len = EVBUFFER_LENGTH(evb);
561 data = EVBUFFER_DATA(evb);
564 hexdump("outgoing packet", data, len);
566 client_send_listener(IMSG_BUF, data, len);
567 evbuffer_drain(evb, len);
571 np_version(uint16_t tag, uint32_t msize, const char *version)
577 msize = htole32(msize);
579 np_header(sizeof(msize) + sizeof(l) + l, Rversion, tag);
580 evbuffer_add(evb, &msize, sizeof(msize));
581 np_string(l, version);
586 np_attach(uint16_t tag, struct qid *qid)
588 np_header(QIDSIZE, Rattach, tag);
594 np_clunk(uint16_t tag)
596 np_header(0, Rclunk, tag);
601 np_flush(uint16_t tag)
603 np_header(0, Rflush, tag);
608 np_walk(uint16_t tag, int nwqid, struct qid *wqid)
612 /* two bytes for the counter */
613 np_header(2 + QIDSIZE * nwqid, Rwalk, tag);
615 for (i = 0; i < nwqid; ++i)
622 np_error(uint16_t tag, const char *errstr)
628 np_header(sizeof(l) + l, Rerror, tag);
629 np_string(l, errstr);
634 np_errno(uint16_t tag)
641 strerror_r(errno, buf, sizeof(buf));
648 np_read8(const char *t, const char *f, uint8_t *dst, const uint8_t **src,
651 if (*len < sizeof(*dst)) {
652 log_warnx("%s: wanted %zu bytes for the %s field but only "
653 "%zu are available.", t, sizeof(*dst), f, *len);
657 memcpy(dst, *src, sizeof(*dst));
658 *src += sizeof(*dst);
659 *len -= sizeof(*dst);
665 np_read16(const char *t, const char *f, uint16_t *dst, const uint8_t **src,
668 if (*len < sizeof(*dst)) {
669 log_warnx("%s: wanted %zu bytes for the %s field but only "
670 "%zu are available.", t, sizeof(*dst), f, *len);
674 memcpy(dst, *src, sizeof(*dst));
675 *src += sizeof(*dst);
676 *len -= sizeof(*dst);
677 *dst = le16toh(*dst);
683 np_read32(const char *t, const char *f, uint32_t *dst, const uint8_t **src,
686 if (*len < sizeof(*dst)) {
687 log_warnx("%s: wanted %zu bytes for the %s field but only "
688 "%zu are available.", t, sizeof(*dst), f, *len);
692 memcpy(dst, *src, sizeof(*dst));
693 *src += sizeof(*dst);
694 *len -= sizeof(*dst);
695 *dst = le32toh(*dst);
701 np_readstr(const char *t, const char *f, char *res, size_t reslen,
702 const uint8_t **src, size_t *len)
707 strlcpy(buf, f, sizeof(buf));
708 strlcat(buf, "-len", sizeof(buf));
710 if (!np_read16(t, buf, &sl, src, len))
714 log_warnx("%s: wanted %d bytes for the %s field but only "
715 "%zu are available.", t, sl, f, *len);
722 memcpy(res, *src, sl);
731 tversion(struct np_msg_header *hdr, const uint8_t *data, size_t len)
733 char *dot, version[32];
738 /* msize[4] version[s] */
739 if (!NPREAD32("msize", &msize, &data, &len))
742 switch (NPREADSTR("version", version, sizeof(version), &data, &len)) {
746 log_warnx("9P version string too long, truncated");
750 if ((dot = strchr(version, '.')) != NULL)
753 if (strcmp(version, VERSION9P) != 0 ||
757 /* version matched */
759 msize = MIN(msize, MSIZE9P);
760 client_send_listener(IMSG_MSIZE, &msize, sizeof(msize));
761 np_version(hdr->tag, msize, VERSION9P);
765 log_warnx("unknown 9P version string: \"%s\", want "VERSION9P,
767 np_version(hdr->tag, MSIZE9P, "unknown");
771 client_send_listener(IMSG_CLOSE, NULL, 0);
776 tattach(struct np_msg_header *hdr, const uint8_t *data, size_t len)
781 char aname[PATH_MAX];
784 np_error(hdr->tag, "already attached");
788 /* fid[4] afid[4] uname[s] aname[s] */
790 if (!NPREAD32("fid", &fid, &data, &len) ||
791 !NPREAD32("afid", &afid, &data, &len))
794 /* read the uname but don't actually use it */
795 switch (NPREADSTR("uname", aname, sizeof(aname), &data, &len)) {
799 np_error(hdr->tag, "name too long");
803 switch (NPREADSTR("aname", aname, sizeof(aname), &data, &len)) {
807 np_error(hdr->tag, "name too long");
811 if ((qid = qid_from_path(aname)) == NULL) {
813 log_debug("failed to attach %s: %s", aname, strerror(errno));
816 log_debug("attached %s", aname);
818 if ((f = new_fid(qid, fid)) == NULL) {
820 np_error(hdr->tag, "no memory");
824 np_attach(hdr->tag, qid);
829 client_send_listener(IMSG_CLOSE, NULL, 0);
834 tclunk(struct np_msg_header *hdr, const uint8_t *data, size_t len)
840 if (!NPREAD32("fid", &fid, &data, &len)) {
841 client_send_listener(IMSG_CLOSE, NULL, 0);
846 if ((f = fid_by_id(fid)) == NULL) {
847 np_error(hdr->tag, "invalid fid");
856 tflush(struct np_msg_header *hdr, const uint8_t *data, size_t len)
861 * We're doing only synchronous I/O. Tflush is implemented
862 * only because it's illegal to reply with a Rerror.
866 if (len != sizeof(oldtag)) {
867 log_warnx("Tclunk with the wrong size: got %zu want %zu",
868 len, sizeof(oldtag));
869 client_send_listener(IMSG_CLOSE, NULL, 0);
878 twalk(struct np_msg_header *hdr, const uint8_t *data, size_t len)
880 struct qid *qid, wqid[MAXWELEM] = {0};
882 uint32_t fid, newfid;
885 char wnam[PATH_MAX+1], path[PATH_MAX+1];
887 if (!NPREAD32("fid", &fid, &data, &len) ||
888 !NPREAD32("newfid", &newfid, &data, &len) ||
889 !NPREAD16("nwname", &nwname, &data, &len))
892 if (nwname > MAXWELEM) {
893 log_warnx("Twalk: more than %d path elements: %d",
898 if ((f = fid_by_id(fid)) == NULL) {
899 np_error(hdr->tag, "invalid fid");
905 else if ((nf = fid_by_id(newfid)) != NULL) {
906 np_error(hdr->tag, "newfid already in use");
911 /* special case: fid duplication */
914 * TODO: should we forbid fids duplication when fid ==
919 if ((nf = new_fid(f->qid, newfid)) == NULL)
920 fatal("new_fid duplication");
923 np_walk(hdr->tag, 1, f->qid);
927 if (f->iomode != 0) {
928 np_error(hdr->tag, "fid already opened for I/O");
932 if (f->qid->type != QTDIR) {
933 np_error(hdr->tag, "fid doesn't represent a directory");
937 strlcpy(path, f->qid->fpath, sizeof(path));
939 for (nwqid = 0; nwqid < nwname; nwqid++) {
940 switch (NPREADSTR("wname", wnam, sizeof(wnam), &data, &len)) {
944 np_error(hdr->tag, "wname too long");
948 strlcat(path, "/", sizeof(path));
949 strlcat(path, wnam, sizeof(path));
951 if (stat(path, &wqid[nwqid].sb) == -1) {
955 np_walk(hdr->tag, nwqid, wqid);
959 qid_set_from_sb(&wqid[nwqid]);
962 if ((qid = qid_from_path(path)) == NULL)
963 fatal("qid_from_fd");
966 if ((nf = new_fid(qid, newfid)) == NULL)
971 nf->qid = qid_incref(qid);
974 np_walk(hdr->tag, nwqid, wqid);
979 client_send_listener(IMSG_CLOSE, NULL, 0);
984 handle_message(struct imsg *imsg, size_t len)
988 void (*fn)(struct np_msg_header *, const uint8_t *, size_t);
990 {Tversion, tversion},
996 struct np_msg_header hdr;
1001 hexdump("incoming packet", imsg->data, len);
1004 parse_message(imsg->data, len, &hdr, &data);
1007 log_debug("got request: len=%d type=%d[%s] tag=%d",
1008 hdr.len, hdr.type, pp_msg_type(hdr.type), hdr.tag);
1010 if (!handshaked && hdr.type != Tversion) {
1011 client_send_listener(IMSG_CLOSE, NULL, 0);
1016 for (i = 0; i < sizeof(msgs)/sizeof(msgs[0]); ++i) {
1017 if (msgs[i].type != hdr.type)
1020 msgs[i].fn(&hdr, data, len);
1024 np_error(hdr.tag, "Not supported.");