Bug 62134 - apr_fnmatch_test is wrong on wild-card string with escape char (backslash)
Summary: apr_fnmatch_test is wrong on wild-card string with escape char (backslash)
Status: NEW
Alias: None
Product: APR
Classification: Unclassified
Component: APR (show other bugs)
Version: HEAD
Hardware: PC All
: P2 major (vote)
Target Milestone: ---
Assignee: Apache Portable Runtime bugs mailinglist
URL:
Keywords: PatchAvailable
Depends on:
Blocks:
 
Reported: 2018-02-26 11:12 UTC by soapand
Modified: 2020-09-16 12:25 UTC (History)
0 users



Attachments
Extra tests for apr_fnmatch_test function. (1.50 KB, text/plain)
2018-02-26 11:12 UTC, soapand
Details

Note You need to log in before you can comment on or make changes to this bug.
Description soapand 2018-02-26 11:12:10 UTC
Created attachment 35745 [details]
Extra tests for apr_fnmatch_test function.

# Problem description
`apr_fnmatch_test` is wrong on wild-card strings with escape character (backslash) and no other special characters.

# Impact
It is not possible to specify some directories in `Directory` of Apache configuration file.

# STR 1

## Steps
1. Install and configure Apache Web server.
2. Create the directories like the following:

	1. `/var/www/vhosts/myhost.example/foo*bar`
	2. `/var/www/vhosts/myhost.example/foo\*bar`
	3. `/var/www/vhosts/myhost.example/fooBAZbar`

3. Try to deny access to `foo*bar` using:

		<Directory "var/www/vhosts/myhost.example/foo*bar">
			Require all denied
		</Directory>
		
4. Remove the previous configuration block and try to deny access to `foo*bar` using:

		<Directory "var/www/vhosts/myhost.example/foo\*bar">
			Require all denied
		</Directory>
	
5. Remove the previous configuration block and try to deny access to `foo*bar` using:

		<Directory "var/www/vhosts/myhost.example/foo\\*bar">
			Require all denied
		</Directory>

## Actual result
On step 3: access to all three directories is denied.
On step 4: access to `foo\*bar` only is denied.
On step 5: access to `foo\*bar` only is denied.

## Expected result
On step 3: access to all three directories is denied.
On step 4: access to `foo*bar` only is denied.
On step 5: access to `foo*bar` only is denied.


# STR 2

## Steps
~~~
gcc test-apr_fnmatch_test.cpp -o test-apr_fnmatch_test -ldl
./test-apr_fnmatch_test
~~~

## Actual result
~~~
[user@host ~]# gcc test-apr_fnmatch_test.cpp -o test-apr_fnmatch_test -ldl
[user@host ~]# ./test-apr_fnmatch_test
apr_fnmatch_test("foo\*bar") returns 0, expected 1
apr_fnmatch_test("foo\bar") returns 0, expected 1
done test_fnmatch_test
~~~

## Expected result
~~~
[root@host ~]# gcc test-apr_fnmatch_test.cpp -o test-apr_fnmatch_test -ldl
[root@host ~]# ./test-apr_fnmatch_test
done test_fnmatch_test
~~~


# Root cause
[apr/strings/apr_fnmatch.c:416-420](https://github.com/apache/apr/blob/71cf5aa36f5c5138d3bad87c6c1e8124b8df457f/strings/apr_fnmatch.c#L416)


# Possible solution
~~~
--- apr/strings/apr_fnmatch.c
+++ apr/strings/apr_fnmatch.c (Unsaved)
@@ -414,10 +414,11 @@
             return 1;
 
         case '\\':
-            if (*++pattern == '\0') {
+            if (*(pattern + 1) == '\0') {
                 return 0;
-            }
-            break;
+            } else {
+                return 1;
+            }
 
         case '[':         /* '[' is only a glob if it has a matching ']' */
             ++nesting;
~~~


# Workaround
Use the following configuration to deny access to `foo*bar`:

	<Directory "var/www/vhosts/myhost.example/foo[*]bar">
		Require all denied
	</Directory>
Comment 1 William A. Rowe Jr. 2018-03-22 02:29:12 UTC
Commenting so that this lands on my radar. Thank you for the report.