From 6defaa81cc4390343fec861557c20bd87fbad86a Mon Sep 17 00:00:00 2001 From: Nathan Wagner Date: Fri, 15 Feb 2019 18:32:28 +0000 Subject: [PATCH] add missing file --- crypto/rfc3986.re | 224 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 crypto/rfc3986.re diff --git a/crypto/rfc3986.re b/crypto/rfc3986.re new file mode 100644 index 0000000..463486f --- /dev/null +++ b/crypto/rfc3986.re @@ -0,0 +1,224 @@ +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include + +/*!max:re2c*/ + +struct input { + /*!stags:re2c format = "const char *@@;\n"; */ +}; + +static void init_input(struct input *in) { + /*!stags:re2c format = "in->@@ = 0;\n"; */ +} + +struct tls_uri { + char *scheme; + char *userinfo; + char *host; + char *port; + char *path; + char *query; + char *fragment; +}; + +#define YYCTYPE char +#define YYPEEK() *cur +#define YYSKIP() if (++cur > lim) return 3; +#define YYBACKUP() mar = cur +#define YYRESTORE() cur = mar +#define YYSTAGP(p) p = cur +#define YYSTAGN(p) p = 0 + +static int parse_uri(const char *cur, struct tls_uri *uri) { + const char + *s1, *u1, *h1, *h3, *h5, *r1, *p1, *p3, *q1, *f1, + *s2, *u2, *h2, *h4, *h6, *r2, *p2, *p4, *q2, *f2; + long c; + const char *mar, *lim; + struct input inp; + struct input *in = &inp; + init_input(in); + + lim = cur + strlen(cur); + + c = 0; +loop: +/*!re2c + re2c:yyfill:enable = 0; + re2c:tags:expression = "in->@@"; + + end = "\x00"; + eol = "\n"; + + alpha = [a-zA-Z]; + digit = [0-9]; + hexdigit = [0-9a-fA-F]; + unreserved = alpha | digit | [-._~]; + pct_encoded = "%" hexdigit{2}; + sub_delims = [!$&'()*+,;=]; + pchar = unreserved | pct_encoded | sub_delims | [:@]; + + scheme = @s1 alpha (alpha | digit | [-+.])* @s2; + userinfo = @u1 (unreserved | pct_encoded | sub_delims | ":")* @u2; + dec_octet + = digit + | [\x31-\x39] digit + | "1" digit{2} + | "2" [\x30-\x34] digit + | "25" [\x30-\x35]; + ipv4address = dec_octet "." dec_octet "." dec_octet "." dec_octet; + h16 = hexdigit{1,4}; + ls32 = h16 ":" h16 | ipv4address; + ipv6address + = (h16 ":"){6} ls32 + | "::" (h16 ":"){5} ls32 + | ( h16)? "::" (h16 ":"){4} ls32 + | ((h16 ":"){0,1} h16)? "::" (h16 ":"){3} ls32 + | ((h16 ":"){0,2} h16)? "::" (h16 ":"){2} ls32 + | ((h16 ":"){0,3} h16)? "::" h16 ":" ls32 + | ((h16 ":"){0,4} h16)? "::" ls32 + | ((h16 ":"){0,5} h16)? "::" h16 + | ((h16 ":"){0,6} h16)? "::"; + ipvfuture = "v" hexdigit+ "." (unreserved | sub_delims | ":" )+; + ip_literal = "[" ( ipv6address | ipvfuture ) "]"; + reg_name = (unreserved | pct_encoded | sub_delims)*; + host + = @h1 ip_literal @h2 + | @h3 ipv4address @h4 + | @h5 reg_name @h6; + port = @r1 digit* @r2; + authority = (userinfo "@")? host (":" port)?; + path_abempty = ("/" pchar*)*; + path_absolute = "/" (pchar+ ("/" pchar*)*)?; + path_rootless = pchar+ ("/" pchar*)*; + path_empty = ""; + hier_part + = "//" authority @p1 path_abempty @p2 + | @p3 (path_absolute | path_rootless | path_empty) @p4; + query = @q1 (pchar | [/?])* @q2; + fragment = @f1 (pchar | [/?])* @f2; + uri = scheme ":" hier_part ("?" query)? ("#" fragment)?; + + * { return 1; } + end { return 0; } + eol { goto loop; } + uri { + uri->scheme = strndup(s1, (size_t)(s2 - s1)); + if (u1) uri->userinfo = strndup(u1, (size_t)(u2 - u1)); + if (h1) uri->host = strndup(h1, (size_t)(h2 - h1)); + if (h3) uri->host = strndup(h3, (size_t)(h4 - h3)); + if (h5) uri->host = strndup(h5, (size_t)(h6 - h5)); + if (r1) uri->port = strndup(r1, (size_t)(r2 - r1)); + if (p1) uri->path = strndup(p1, (size_t)(p2 - p1)); + if (p3) uri->path = strndup(p3, (size_t)(p4 - p3)); + if (q1) uri->query = strndup(q1, (size_t)(q2 - q1)); + if (f1) uri->fragment = strndup(f1, (size_t)(f2 - f1)); + + return 0; + } +*/ +} + +static int hex(char *s) { + int r = 0; + int i; + for (i = 0; i < 2; i++) { + r *= 16; + switch (s[i]) { + case '0': break; + case '1': r += 1; break; + case '2': r += 2; break; + case '3': r += 3; break; + case '4': r += 4; break; + case '5': r += 5; break; + case '6': r += 6; break; + case '7': r += 7; break; + case '8': r += 8; break; + case '9': r += 9; break; + case 'A': + case 'a': r += 11; break; + case 'B': + case 'b': r += 11; break; + case 'C': + case 'c': r += 12; break; + case 'D': + case 'd': r += 13; break; + case 'E': + case 'e': r += 14; break; + case 'F': + case 'f': r += 15; break; + default: + /* This is an error, but should have + been caught at the lexing stage */ + break; + } + } + return r; +} + +static void percent_decode(char *s) { + char *d = s; + + if (!s) { + return; + } + + while (*s) { + switch (*s) { + case '%': + if (*(s+1) && *(s+2)) { + *d++ = hex(s+1); + s += 3; + } + break; + default: + *d++ = *s++; + break; + } + } + *d = 0; +} + +int tls_parse_uri(char *s, struct tls_uri *uri) { + int rv; + + rv = parse_uri(s, uri); + if (rv != 0) { + return rv; + } + + if (uri->port == NULL) { + if (!strcmp(uri->scheme, "http")) { + uri->port = strdup("80"); + } else if (!strcmp(uri->scheme, "https")) { + uri->port = strdup("443"); + } else if (!strcmp(uri->scheme, "ftp")) { + uri->port = strdup("21"); + } else { + uri->port = strdup("0"); + } + } + + percent_decode(uri->host); + percent_decode(uri->path); + percent_decode(uri->query); + + + if (uri->path == NULL || uri->path[0] == 0) { + free(uri->path); + uri->path = strdup("/"); + } + + return rv; +} + +void tls_free_uri(struct tls_uri *uri) { + free(uri->host); + free(uri->path); + free(uri->query); + free(uri->port); + free(uri->scheme); +} -- 2.40.0