From 9c95539a7ec300801fe2d858ecc6c59babb51078 Mon Sep 17 00:00:00 2001 From: Wesley Miaw Date: Fri, 12 Jun 2020 18:24:27 -0700 Subject: [PATCH] Allow wildcard matches for non-https schemes of the form scheme://* and scheme:*. --- client/makefile | 6 ++---- server/dial_server.c | 39 +++++++++++++++++++++++++++++++++------ server/main.c | 6 +++--- server/makefile | 6 ++---- server/tests/test_cors.sh | 8 ++++---- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/client/makefile b/client/makefile index 61bc528..22a1dde 100644 --- a/client/makefile +++ b/client/makefile @@ -6,14 +6,12 @@ CC=$(TARGET)g++ includes = $(wildcard *.h) OBJS := main.cpp DialServer.cpp DialDiscovery.cpp DialConformance.cpp DialClientInput.cpp -debug: dialclient_debug +debug: CFLAGS += -DDEBUG +debug: dialclient # You may not need all these libraries. This example uses a build of curl that needs crypto, ssl, cares, and zlib dialclient: $(OBJS) ${includes} $(CC) -Wall -Werror -g $(OBJS) $(INCLUDES) $(LDFLAGS) -ldl -lpthread -lcurl -lz -lcrypto -lssl -o dialclient -dialclient_debug: $(OBJS) ${includes} - $(CC) -DDEBUG -Wall -Werror -g $(OBJS) $(INCLUDES) $(LDFLAGS) -ldl -lpthread -lcurl -lz -lcrypto -lssl -lcares -o dialclient_debug - clean: rm -f *.o dialclient diff --git a/server/dial_server.c b/server/dial_server.c index 8cb5ed9..6f8bfab 100644 --- a/server/dial_server.c +++ b/server/dial_server.c @@ -502,8 +502,8 @@ static void handle_dial_data(struct mg_connection *conn, * it will not include invalid characters or a non-numeric port number. * * @param origin the origin header value, which must begin with https:// - * @param candidate the accepted origin whitelist value, which must begin - * with https:// + * @param candidate the authorized origin value, which must begin with + * https:// * @return true if accepted and false if not. */ static int host_matches(const char *origin, const char *candidate) { @@ -596,13 +596,40 @@ static int host_matches(const char *origin, const char *candidate) { strncmp(origin_host, host, origin_len) == 0); } +/** + * Returns true if the origin is acceptable based on the candidate value. + * The origin must be an exact match to the candidate, unless the + * candidate is of the form 'scheme://*' or 'scheme:*' in which case + * everything before the wildcard '*' character must be an exact match but + * anything is accepted in place of the wildcard. + * + * This function assumes that the candidate value is well-formed, meaning + * it will not include invalid chracters and it will be a valid URI. + * + * @param origin the origin header value. + * @param candidate the authorized origin value. + * @return true if accepted and false if not. + */ static int origin_matches(const char *origin, const char *candidate) { // Make sure there is something to compare. if (!origin || !candidate) return 0; - - // Require an exact match. + + // If the candidate consists of a scheme followed by wildcard, + // require an exact match of the scheme specifier. size_t origin_len = strlen(origin); + size_t candidate_len = strlen(candidate); + if (candidate_len > 1 && candidate[candidate_len - 1] == '*') { + // The origin must be at least as long as the candidate for a + // wildcard match to succeed. + if (origin_len < candidate_len) + return 0; + + fprintf(stderr, "comparing %s to %s len %lld\n", origin, candidate, candidate_len); + return strncmp(origin, candidate, candidate_len - 1) == 0; + } + + // Require an exact match. return (origin_len == strlen(candidate) && strncmp(origin, candidate, origin_len) == 0); } @@ -639,8 +666,8 @@ static int is_uri_in_list(const char *origin, const char *list) { candidate[copyLength] = '\0'; //printf("found %s \n", candidate); // If the URI begins with https://, perform a host comparison because - // any port numbers must be handled specially. Otherwise require an - // exact match. + // any port numbers must be handled specially. Otherwise perform a + // regular match. if ((isHttps && host_matches(origin, candidate)) || (!isHttps && origin_matches(origin, candidate))) { diff --git a/server/main.c b/server/main.c index 69ba304..6e36a82 100644 --- a/server/main.c +++ b/server/main.c @@ -289,11 +289,11 @@ void runDial(void) struct DIALAppCallbacks cb_system = {system_start, system_hide, NULL, system_status}; #if defined DEBUG - if (DIAL_register_app(ds, "Netflix", &cb_nf, NULL, 1, "https://netflix.com https://www.netflix.com https://port.netflix.com:123") == -1 || - DIAL_register_app(ds, "YouTube", &cb_yt, NULL, 1, "https://youtube.com https://www.youtube.com https://*.youtube.com:443 https://port.youtube.com:123 package:com.google.android.youtube package:com.google.ios.youtube") == -1 || + if (DIAL_register_app(ds, "Netflix", &cb_nf, NULL, 1, "https://netflix.com https://www.netflix.com https://port.netflix.com:123 proto://*") == -1 || + DIAL_register_app(ds, "YouTube", &cb_yt, NULL, 1, "https://youtube.com https://www.youtube.com https://*.youtube.com:443 https://port.youtube.com:123 package:com.google.android.youtube package:com.google.ios.youtube proto:*") == -1 || #else if (DIAL_register_app(ds, "Netflix", &cb_nf, NULL, 1, "https://netflix.com https://www.netflix.com") == -1 || - DIAL_register_app(ds, "YouTube", &cb_yt, NULL, 1, "https://youtube.com https://*.youtube.com package:com.google.android.youtube package:com.google.ios.youtube") == -1 || + DIAL_register_app(ds, "YouTube", &cb_yt, NULL, 1, "https://youtube.com https://*.youtube.com package:*") == -1 || #endif DIAL_register_app(ds, "system", &cb_system, NULL, 1, "") == -1) { diff --git a/server/makefile b/server/makefile index cca618c..533d248 100644 --- a/server/makefile +++ b/server/makefile @@ -13,7 +13,8 @@ HEADERS := $(wildcard *.h) $(CC) -Wall -g -fPIC -std=gnu99 $(CFLAGS) -c $*.c -o $*.o all: dialserver -debug: dialserver_debug test +debug: CFLAGS += -DDEBUG +debug: dialserver test nf_callbacks_lib: nf_callbacks.o # $(CC) -Wall -Werror -g nf_callbacks.o -o libnfCallbacks.so --shared @@ -22,9 +23,6 @@ nf_callbacks_lib: nf_callbacks.o dialserver: nf_callbacks_lib $(OBJS) $(CC) -Wall -Werror -Wl,-rpath,. -g $(OBJS) -ldl -lpthread -lrt -L. -lnfCallbacks -o dialserver -dialserver_debug: nf_callbacks_lib $(OBJS) - $(CC) -DDEBUG -Wall -Werror -Wl,-rpath,. -g $(OBJS) -ldl -lpthread -lrt -L. -lnfCallbacks -o dialserver - dialserver_with_ASAN: nf_callbacks_lib $(OBJS) $(CC) -Wall -Werror -fsanitize=address -Wl,-rpath,. -g $(OBJS) -ldl -lpthread -lrt -L. -lnfCallbacks -o dialserver_with_ASAN diff --git a/server/tests/test_cors.sh b/server/tests/test_cors.sh index f51304c..38e83da 100755 --- a/server/tests/test_cors.sh +++ b/server/tests/test_cors.sh @@ -9,7 +9,7 @@ ip_address=$1 port=$2 #Testing all the positive cases -origins="https://www.netflix.com https://netflix.com https://port.netflix.com:123 https://www.netflix.com:80 https://www.netflix.com:123" +origins="https://www.netflix.com https://netflix.com https://port.netflix.com:123 https://www.netflix.com:80 https://www.netflix.com:123 proto://netflix.com proto://netflix proto://netflix.com:123" for origin in $origins; do curl --fail --silent --header "Origin:$origin" --data "v=QH2-TGUlwu4" http://$ip_address:$port/apps/Netflix || echo "failed: $origin should be accepted" curl --fail --silent --header "Origin:$origin" -X OPTIONS http://$ip_address:$port/apps/Netflix || echo "failed: $origin should be accepted" @@ -21,7 +21,7 @@ then fi done -origins="https://www.youtube.com https://music.youtube.com https://youtube.com https://port.youtube.com:123 https://www.youtube.com:80 https://www.youtube.com:123 package:com.google.android.youtube package:com.google.ios.youtube" +origins="https://www.youtube.com https://music.youtube.com https://youtube.com https://port.youtube.com:123 https://www.youtube.com:80 https://www.youtube.com:123 package:com.google.android.youtube package:com.google.ios.youtube proto:g proto:com.google" for origin in $origins; do curl --fail --silent --header "Origin:$origin" --data "v=QH2-TGUlwu4" http://$ip_address:$port/apps/YouTube || echo "failed: $origin should be accepted" curl --fail --silent --header "Origin:$origin" -X OPTIONS http://$ip_address:$port/apps/YouTube || echo "failed: $origin should be accepted" @@ -34,7 +34,7 @@ fi done #Testing all the negative cases -origins="http://www.netflix-a.com http://www.netflix.com4 http://a-netflix.com http://www4.netflix.com https://port.netflix.com:1234 http://1.netflix.com https://www4.netflix.com https://ww.netflix-a.com https://www.netflix.com4 https://a-netflix.com http://netflix.com http://www.attack.com https://www.attack.com file://www.attack.com ftp://this.is.not.fine package: package:com.netflix.null" +origins="http://www.netflix-a.com http://www.netflix.com4 http://a-netflix.com http://www4.netflix.com https://port.netflix.com:1234 http://1.netflix.com https://www4.netflix.com https://ww.netflix-a.com https://www.netflix.com4 https://a-netflix.com http://netflix.com http://www.attack.com https://www.attack.com file://www.attack.com ftp://this.is.not.fine package: package:com.netflix.null proto:// proto:n proto:/n proto" for origin in $origins; do curl --fail --silent --header "Origin:$origin" --data "v=QH2-TGUlwu4" http://$ip_address:$port/apps/Netflix && echo "failed: $origin should be rejected" curl --fail --silent --header "Origin:$origin" -X OPTIONS http://$ip_address:$port/apps/Netflix && echo "failed: $origin should be rejected" @@ -46,7 +46,7 @@ then fi done -origins="http://www.youtube-a.com http://www.youtube.com4 https://.youtube.com http://a-youtube.com https://ww.youtube-a.com http://www4.youtube.com https://port.youtube.com:1234 http://1.youtube.com https://www.youtube.com4 https://a-youtube.com http://youtube.com http://www.attack.com https://www.attack.com file://www.attack.com ftp://this.is.not.fine packagecom.google.android.youtube package:com.google.android.utube" +origins="http://www.youtube-a.com http://www.youtube.com4 https://.youtube.com http://a-youtube.com https://ww.youtube-a.com http://www4.youtube.com https://port.youtube.com:1234 http://1.youtube.com https://www.youtube.com4 https://a-youtube.com http://youtube.com http://www.attack.com https://www.attack.com file://www.attack.com ftp://this.is.not.fine packagecom.google.android.youtube package:com.google.android.utube packagea package: pack:com.google.android protoa proto:" for origin in $origins; do curl --fail --silent --header "Origin:$origin" --data "v=QH2-TGUlwu4" http://$ip_address:$port/apps/YouTube && echo "failed: $origin should be rejected" curl --fail --silent --header "Origin:$origin" -X OPTIONS http://$ip_address:$port/apps/YouTube && echo "failed: $origin should be rejected"