commit 5c485996696ebb2f12799297a00ef02d89d91246 from: Omar Polo date: Wed Jul 28 21:36:24 2021 UTC initial Tversion handling commit - 2bf43d27c2a9ef1adf1dddf45a3bd685d518b45d commit + 5c485996696ebb2f12799297a00ef02d89d91246 blob - 4f46a4a6100f51eddfb822e354d336daa0c77cb9 blob + 652cf8c8e71ac26adb15fc524c3eee92bcbbcdaa --- client.c +++ client.c @@ -35,12 +35,18 @@ static struct imsgev *iev_listener; static struct evbuffer *evb; static uint32_t peerid; +static int handshaked; +uint32_t msize; + static ATTR_DEAD void client_shutdown(void); static void client_sig_handler(int, short, void *); static void client_dispatch_listener(int, short, void *); static void client_privdrop(const char *, const char *); static int client_send_listener(int, const void *, uint16_t); + +static void parse_message(uint8_t *, size_t, struct np_msg_header *, + uint8_t **); static void np_error(uint16_t, const char *); @@ -245,8 +251,9 @@ client_send_listener(int type, const void *data, uint1 return ret; } -static inline void -parse_message(uint8_t *data, size_t len, struct np_msg_header *hdr, void **cnt) +static void +parse_message(uint8_t *data, size_t len, struct np_msg_header *hdr, + uint8_t **cnt) { if (len < 4) goto err; @@ -292,6 +299,16 @@ np_header(uint32_t len, uint8_t type, uint16_t tag) evbuffer_add(evb, &len, sizeof(len)); evbuffer_add(evb, &type, sizeof(type)); evbuffer_add(evb, &tag, sizeof(tag)); +} + +static inline void +np_string(uint16_t len, const char *str) +{ + uint16_t l = len; + + len = htole16(len); + evbuffer_add(evb, &len, sizeof(len)); + evbuffer_add(evb, str, l); } static inline void @@ -306,6 +323,23 @@ do_send(void) } static void +np_version(uint16_t tag, uint32_t msize, const char *version) +{ + uint32_t len = HEADERSIZE; + uint16_t l; + + l = strlen(version); + len += sizeof(msize) + sizeof(l) + l; + + msize = htole32(msize); + + np_header(len, Rversion, tag); + evbuffer_add(evb, &msize, sizeof(msize)); + np_string(l, version); + do_send(); +} + +static void np_error(uint16_t tag, const char *errstr) { uint32_t len = HEADERSIZE; @@ -315,21 +349,66 @@ np_error(uint16_t tag, const char *errstr) len += sizeof(l) + l; np_header(len, Rerror, tag); - evbuffer_add(evb, &l, sizeof(l)); - evbuffer_add(evb, errstr, l); - + np_string(l, errstr); do_send(); } static void handle_message(struct imsg *imsg, size_t len) { - struct np_msg_header hdr; - void *data; + struct np_msg_header hdr; + uint16_t slen; + uint8_t *data; parse_message(imsg->data, len, &hdr, &data); + len -= HEADERSIZE; - /* for now, log the request and reply with an error. */ - log_debug("got request type %s", pp_msg_type(hdr.type)); - np_error(hdr.tag, "Not supported."); + log_debug("got request: len=%d type=%d[%s] tag=%d", + hdr.len, hdr.type, pp_msg_type(hdr.type), hdr.tag); + + if (!handshaked && hdr.type != Tversion) + goto err; + + switch (hdr.type) { + case Tversion: + if (handshaked) + goto err; + + /* msize[4] + version[s] */ + if (len < 6) + goto err; + + memcpy(&msize, data, sizeof(msize)); + data += sizeof(msize); + len = le32toh(len); + + memcpy(&slen, data, sizeof(slen)); + data += sizeof(slen); + slen = le16toh(slen); + + if (slen != strlen(VERSION9P) || + memcpy(data, VERSION9P, strlen(VERSION9P)) != 0 || + msize == 0) { + np_version(hdr.tag, MSIZE9P, "unknown"); + return; + } + + handshaked = 1; + + msize = MIN(msize, MSIZE9P); + client_send_listener(IMSG_MSIZE, &msize, sizeof(msize)); + np_version(hdr.tag, msize, VERSION9P); + break; + + default: + /* for now, log the request and reply with an error. */ + np_error(hdr.tag, "Not supported."); + break; + } + + return; + +err: + client_send_listener(IMSG_CLOSE, NULL, 0); + client_shutdown(); } blob - 4f58841a8c8c7dc714b0b7f4ef54034e6fefd90d blob + 313f07d8e6f7e00f60bd8efec086ac5edae8a8f1 --- kamid.h +++ kamid.h @@ -56,6 +56,8 @@ enum imsg_type { IMSG_AUTH_TLS, IMSG_CONN_GONE, IMSG_BUF, + IMSG_MSIZE, + IMSG_CLOSE, }; struct kd_options_conf { blob - b9cb509cb9873fee593543536b0fc8c8a5b486ae blob + 46ad95e3716e051f2e3e9c2e1e60b2872bad4f76 --- listener.c +++ listener.c @@ -477,6 +477,29 @@ listener_dispatch_client(int fd, short event, void *d) break; } break; + + case IMSG_MSIZE: + if (IMSG_DATA_SIZE(imsg) != sizeof(client->msize)) + fatal("IMSG_MSIZE size mismatch: " + "got %zu want %zu", IMSG_DATA_SIZE(imsg), + sizeof(client->msize)); + + memcpy(&client->msize, imsg.data, + sizeof(client->msize)); + + if (client->msize == 0) + fatal("IMSG_MSIZE got msize = 0"); + + break; + + case IMSG_CLOSE: + /* + * Both EVBUFFER_READ or EVBUFFER_WRITE should + * be fine. + */ + client_error(client->bev, EVBUFFER_READ, client); + break; + default: log_debug("%s: unexpected imsg %d", __func__, imsg.hdr.type);