commit a2fd80132769e268bee6af754eca6eb13035de78 from: Omar Polo date: Fri Jan 29 17:11:03 2021 UTC puny_decode: set an error string commit - 22a742e4cb81812769f1efa6e24ee24ad10f1a60 commit + a2fd80132769e268bee6af754eca6eb13035de78 blob - 7f9216e14774690e29c10e082732daf65c9dd451 blob + 2b6a1c86c9ed55ad4c9710bbe351fcecffb2bd66 --- gmid.h +++ gmid.h @@ -240,7 +240,7 @@ int parse_iri(char*, struct iri*, const char**); int trim_req_iri(char*, const char **); /* puny.c */ -int puny_decode(const char*, char*, size_t); +int puny_decode(const char*, char*, size_t, const char**); /* utils.c */ int starts_with(const char*, const char*); blob - c84f4e01a9fe6b4ae81f8447d7f89e48876cdf5e blob + 8bb66c1953b8269da0a14fd85ed9f4ec01e7eb81 --- puny.c +++ puny.c @@ -91,26 +91,34 @@ digit_value(char c) } static int -insert(char *out, size_t len, int codepoint, size_t i) +insert(char *out, size_t len, int codepoint, size_t i, char **err) { int l; char *t; - if (codepoint <= 0x7F) + if (codepoint <= 0x7F) { + *err = "puny: invalid decoded character (ASCII range)"; return 0; - else if (codepoint <= 0x7FF) + } else if (codepoint <= 0x7FF) { l = 2; - else if (codepoint <= 0xFFFF) + } else if (codepoint <= 0xFFFF) { l = 3; - else if (codepoint <= 0x10FFFF) + } else if (codepoint <= 0x10FFFF) { l = 4; - else + } else { + *err = "puny: invalid decoded character"; return 0; + } - if ((t = utf8_nth(out, i)) == NULL) + if ((t = utf8_nth(out, i)) == NULL) { + *err = "puny: invalid insert position"; return 0; - if (t + l >= out + len) + } + + if (t + l >= out + len) { + *err = "puny: insert would overflow"; return 0; + } memmove(t + l, t, strlen(t)); @@ -135,7 +143,7 @@ insert(char *out, size_t len, int codepoint, size_t i) } static int -decode(const char *str, char *out, size_t len) +decode(const char *str, char *out, size_t len, const char **err) { size_t i; uint32_t n; @@ -152,8 +160,10 @@ decode(const char *str, char *out, size_t len) str += 4; if (strchr(str, '-') != NULL) { - if ((s = copy_label(str, out, len)) == NULL) + if ((s = copy_label(str, out, len)) == NULL) { + *err = "puny: invalid label"; return 0; + } if (*s == '-') s++; } else @@ -170,8 +180,10 @@ decode(const char *str, char *out, size_t len) w = 1; for (k = BASE; ; k += BASE) { - if (*s == '\0') + if (*s == '\0') { + *err = "puny: label truncated?"; return 0; + } /* fail eventually? */ digit = digit_value(*s); s++; @@ -213,7 +225,7 @@ end_of_label(const char *hostname) } int -puny_decode(const char *hostname, char *out, size_t len) +puny_decode(const char *hostname, char *out, size_t len, const char **err) { char label[LABEL_LEN]; const char *s, *end; @@ -227,24 +239,30 @@ puny_decode(const char *hostname, char *out, size_t le for (;;) { end = end_of_label(s); l = end - s; - if (l >= sizeof(label)) + if (l >= sizeof(label)) { + *err = "label too long"; return 0; + } memcpy(label, s, l); label[l] = '\0'; - if (!decode(label, out, len)) + if (!decode(label, out, len, err)) return 0; if (*end == '\0') return 1; - if (strlcat(out, ".", len) >= len) + if (strlcat(out, ".", len) >= len) { + *err = "domain name too long"; return 0; + } l = strlen(out); - if (l >= len) + if (l >= len) { + *err = "domain name too long"; return 0; + } out += l; len -= l; blob - f19116fa076b5d3e18a5593ca0bbe99e049b12d6 blob + 137103ff3985eeaba927c7d38e0c0c205856cb69 --- server.c +++ server.c @@ -320,14 +320,13 @@ handle_open_conn(struct pollfd *fds, struct client *c) } if (!trim_req_iri(c->req, &parse_err) - || !parse_iri(c->req, &c->iri, &parse_err)) { + || !parse_iri(c->req, &c->iri, &parse_err) + || !puny_decode(c->iri.host, decoded, sizeof(decoded), &parse_err)) { LOGI(c, "iri parse error: %s", parse_err); start_reply(fds, c, BAD_REQUEST, "invalid request"); return; } - puny_decode(c->iri.host, decoded, sizeof(decoded)); - if (c->iri.port_no != conf.port || strcmp(c->iri.schema, "gemini") || strcmp(decoded, c->domain)) {