From 614b069b63f522f5846df4a622ed56faedcbbb6b Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Tue, 5 Nov 2024 13:19:49 +0200 Subject: [PATCH] lib: uri - Allow parameters directly with semicolon Fixes AAA validation. --- src/lib/test-uri.c | 29 +++++++++++++++++++++++++++-- src/lib/uri-util.c | 27 +++++++++++++++++++++------ src/lib/uri-util.h | 3 +++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/lib/test-uri.c b/src/lib/test-uri.c index efb1703127..9b0edf8ee8 100644 --- a/src/lib/test-uri.c +++ b/src/lib/test-uri.c @@ -507,14 +507,12 @@ const char *rfc_uri_tests[] = { /* from RFC 6694 */ "about:blank", /* from RFC 6733 */ -#if 0 // these don't comply with RFC 3986 "aaa://host.example.com;transport=tcp", "aaa://host.example.com:6666;transport=tcp", "aaa://host.example.com;protocol=diameter", "aaa://host.example.com:6666;protocol=diameter", "aaa://host.example.com:6666;transport=tcp;protocol=diameter", "aaa://host.example.com:1813;transport=udp;protocol=radius", -#endif /* from RFC 6787 */ "session:request1@form-level.store", "session:help@root-level.store", @@ -800,10 +798,37 @@ static void test_uri_escape(void) test_end(); } +static void test_uri_aaa(void) +{ + test_begin("uri aaa"); + + const char *uri = "aaa://host.example.com:6666;transport=tcp;protocol=diameter"; + struct uri_parser parser; + uri_parser_init(&parser, pool_datastack_create(), uri); + parser.semicolon_params = TRUE; + + const char *scheme; + struct uri_authority auth; + const char *query; + int ret; + ret = uri_parse_scheme(&parser, &scheme); + test_assert(ret > 0); + test_assert_strcmp(scheme, "aaa"); + ret = uri_parse_slashslash_host_authority(&parser, &auth); + test_assert(ret > 0); + test_assert_strcmp(auth.host.name, "host.example.com"); + test_assert_ucmp(auth.port, ==, 6666); + ret = uri_parse_query(&parser, &query); + test_assert(ret > 0); + test_assert_strcmp(query, "transport=tcp;protocol=diameter"); + test_end(); +} + void test_uri(void) { test_uri_valid(); test_uri_invalid(); test_uri_rfc(); test_uri_escape(); + test_uri_aaa(); } diff --git a/src/lib/uri-util.c b/src/lib/uri-util.c index 9bec8817cf..12e3c5ec26 100644 --- a/src/lib/uri-util.c +++ b/src/lib/uri-util.c @@ -789,6 +789,10 @@ uri_do_parse_authority(struct uri_parser *parser, struct uri_authority *auth, switch (*parser->cur) { case ':': case '/': case '?': case '#': break; + case ';': + if (parser->semicolon_params) + break; + /* fall-through */ default: if (parser->parse_prefix) break; @@ -808,6 +812,10 @@ uri_do_parse_authority(struct uri_parser *parser, struct uri_authority *auth, switch (*parser->cur) { case '/': case '?': case '#': break; + case ';': + if (parser->semicolon_params) + break; + /* fall-through */ default: if (parser->parse_prefix) break; @@ -1009,7 +1017,9 @@ int uri_parse_query(struct uri_parser *parser, const char **query_r) query = *( pchar / "/" / "?" ) pchar = unreserved / pct-encoded / sub-delims / ":" / "@" */ - if (parser->cur >= parser->end || *parser->cur != '?') + if (parser->cur >= parser->end || + (!parser->semicolon_params && *parser->cur != '?') || + (parser->semicolon_params && *parser->cur != ';')) return 0; parser->cur++; @@ -1135,11 +1145,16 @@ int uri_parse_absolute_generic(struct uri_parser *parser, */ /* scheme ":" */ - if ((flags & URI_PARSE_SCHEME_EXTERNAL) == 0 && - (ret = uri_parse_scheme(parser, NULL)) <= 0) { - if (ret == 0) - parser->error = "Missing scheme"; - return -1; + if ((flags & URI_PARSE_SCHEME_EXTERNAL) == 0) { + const char *scheme; + if ((ret = uri_parse_scheme(parser, &scheme)) <= 0) { + if (ret == 0) + parser->error = "Missing scheme"; + return -1; + } + if (strcmp(scheme, "aaa") == 0 || + (flags & URI_PARSE_SEMICOLON_PARAMS) != 0) + parser->semicolon_params = TRUE; } /* "//" authority */ diff --git a/src/lib/uri-util.h b/src/lib/uri-util.h index a8753b8b10..29283bd09e 100644 --- a/src/lib/uri-util.h +++ b/src/lib/uri-util.h @@ -12,6 +12,8 @@ enum uri_parse_flags { URI_PARSE_SCHEME_EXTERNAL = BIT(0), /* Allow '#fragment' part in URI */ URI_PARSE_ALLOW_FRAGMENT_PART = BIT(1), + /* Allow ';param' after host - violates RFC3986 */ + URI_PARSE_SEMICOLON_PARAMS = BIT(2), }; struct uri_host { @@ -37,6 +39,7 @@ struct uri_parser { bool allow_pct_nul:1; bool parse_prefix:1; + bool semicolon_params:1; }; static inline const char *uri_char_sanitize(unsigned char c) -- 2.47.3