Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
apache-commons-io.19114
apache-commons-io-CVE-2021-29425.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File apache-commons-io-CVE-2021-29425.patch of Package apache-commons-io.19114
From 2736b6fe0b3fa22ec8e2b4184897ecadb021fc78 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig <stefan.bodewig@innoq.com> Date: Thu, 21 Dec 2017 13:49:06 +0100 Subject: [PATCH 2088/2940] IO-559 verify hostname part of suspected UNC paths in FileNameUtils --- .../org/apache/commons/io/FilenameUtils.java | 147 +++++++++++++++++- .../commons/io/FilenameUtilsTestCase.java | 18 +++ 2 files changed, 164 insertions(+), 1 deletion(-) Index: commons-io-2.4-src/src/main/java/org/apache/commons/io/FilenameUtils.java =================================================================== --- commons-io-2.4-src.orig/src/main/java/org/apache/commons/io/FilenameUtils.java +++ commons-io-2.4-src/src/main/java/org/apache/commons/io/FilenameUtils.java @@ -19,8 +19,12 @@ package org.apache.commons.io; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.Stack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * General filename and filepath manipulation utilities. @@ -666,7 +670,9 @@ public class FilenameUtils { } posUnix = posUnix == -1 ? posWin : posUnix; posWin = posWin == -1 ? posUnix : posWin; - return Math.min(posUnix, posWin) + 1; + int pos = Math.min(posUnix, posWin) + 1; + String hostnamePart = filename.substring(2, pos - 1); + return isValidHostName(hostnamePart) ? pos : -1; } else { return isSeparator(ch0) ? 1 : 0; } @@ -1398,4 +1404,143 @@ public class FilenameUtils { return list.toArray( new String[ list.size() ] ); } + /** + * Checks whether a given string is a valid host name according to + * RFC 3986. + * + * <p>Accepted are IP addresses (v4 and v6) as well as what the + * RFC calls a "reg-name". Percent encoded names don't seem to be + * valid names in UNC paths.</p> + * + * @see "https://tools.ietf.org/html/rfc3986#section-3.2.2" + * @param name the hostname to validate + * @return true if the given name is a valid host name + */ + private static boolean isValidHostName(String name) { + return isIPv4Address(name) || isIPv6Address(name) || isRFC3986HostName(name); + } + + private static final Pattern IPV4_PATTERN = + Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"); + private static final int IPV4_MAX_OCTET_VALUE = 255; + + // mostly copied from org.apache.commons.validator.routines.InetAddressValidator#isValidInet4Address + private static boolean isIPv4Address(String name) { + Matcher m = IPV4_PATTERN.matcher(name); + if (!m.matches() || m.groupCount() != 4) { + return false; + } + + // verify that address subgroups are legal + for (int i = 1; i < 5; i++) { + String ipSegment = m.group(i); + if (ipSegment == null || ipSegment.length() == 0) { + return false; + } + + int iIpSegment = 0; + + try { + iIpSegment = Integer.parseInt(ipSegment); + } catch(NumberFormatException e) { + return false; + } + + if (iIpSegment > IPV4_MAX_OCTET_VALUE) { + return false; + } + + if (ipSegment.length() > 1 && ipSegment.startsWith("0")) { + return false; + } + + } + + return true; + } + + private static final int IPV6_MAX_HEX_GROUPS = 8; + private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4; + private static final int MAX_UNSIGNED_SHORT = 0xffff; + private static final int BASE_16 = 16; + + // copied from org.apache.commons.validator.routines.InetAddressValidator#isValidInet6Address + private static boolean isIPv6Address(String inet6Address) { + boolean containsCompressedZeroes = inet6Address.contains("::"); + if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) { + return false; + } + if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::")) + || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) { + return false; + } + String[] octets = inet6Address.split(":"); + if (containsCompressedZeroes) { + List<String> octetList = new ArrayList<String>(Arrays.asList(octets)); + if (inet6Address.endsWith("::")) { + // String.split() drops ending empty segments + octetList.add(""); + } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) { + octetList.remove(0); + } + octets = octetList.toArray(new String[octetList.size()]); + } + if (octets.length > IPV6_MAX_HEX_GROUPS) { + return false; + } + int validOctets = 0; + int emptyOctets = 0; // consecutive empty chunks + for (int index = 0; index < octets.length; index++) { + String octet = octets[index]; + if (octet.length() == 0) { + emptyOctets++; + if (emptyOctets > 1) { + return false; + } + } else { + emptyOctets = 0; + // Is last chunk an IPv4 address? + if (index == octets.length - 1 && octet.contains(".")) { + if (!isIPv4Address(octet)) { + return false; + } + validOctets += 2; + continue; + } + if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) { + return false; + } + int octetInt = 0; + try { + octetInt = Integer.parseInt(octet, BASE_16); + } catch (NumberFormatException e) { + return false; + } + if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) { + return false; + } + } + validOctets++; + } + if (validOctets > IPV6_MAX_HEX_GROUPS || (validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes)) { + return false; + } + return true; + } + + private static final Pattern REG_NAME_PART_PATTERN = Pattern.compile("^[a-zA-Z0-9][a-zA-Z0-9-]*$"); + + private static boolean isRFC3986HostName(String name) { + String[] parts = name.split("\\.", -1); + for (int i = 0; i < parts.length; i++) { + if (parts[i].length() == 0) { + // trailing dot is legal, otherwise we've hit a .. sequence + return i == parts.length - 1; + } + if (!REG_NAME_PART_PATTERN.matcher(parts[i]).matches()) { + return false; + } + } + return true; + } } Index: commons-io-2.4-src/src/test/java/org/apache/commons/io/FilenameUtilsTestCase.java =================================================================== --- commons-io-2.4-src.orig/src/test/java/org/apache/commons/io/FilenameUtilsTestCase.java +++ commons-io-2.4-src/src/test/java/org/apache/commons/io/FilenameUtilsTestCase.java @@ -216,6 +216,15 @@ public class FilenameUtilsTestCase exten assertEquals(null, FilenameUtils.normalize("//server/../a")); assertEquals(null, FilenameUtils.normalize("//server/..")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalize("//server/")); + + assertEquals(SEP + SEP + "127.0.0.1" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\127.0.0.1\\a\\b\\c.txt")); + assertEquals(SEP + SEP + "::1" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\::1\\a\\b\\c.txt")); + assertEquals(SEP + SEP + "server.example.org" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\server.example.org\\a\\b\\c.txt")); + assertEquals(SEP + SEP + "server." + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\server.\\a\\b\\c.txt")); + + assertEquals(null, FilenameUtils.normalize("\\\\-server\\a\\b\\c.txt")); + assertEquals(null, FilenameUtils.normalize("\\\\.\\a\\b\\c.txt")); + assertEquals(null, FilenameUtils.normalize("\\\\..\\a\\b\\c.txt")); } public void testNormalizeUnixWin() throws Exception { @@ -503,7 +512,17 @@ public class FilenameUtilsTestCase exten assertEquals(1, FilenameUtils.getPrefixLength("\\a\\b\\c.txt")); assertEquals(2, FilenameUtils.getPrefixLength("~\\a\\b\\c.txt")); assertEquals(6, FilenameUtils.getPrefixLength("~user\\a\\b\\c.txt")); - } + + assertEquals(12, FilenameUtils.getPrefixLength("\\\\127.0.0.1\\a\\b\\c.txt")); + assertEquals(6, FilenameUtils.getPrefixLength("\\\\::1\\a\\b\\c.txt")); + assertEquals(21, FilenameUtils.getPrefixLength("\\\\server.example.org\\a\\b\\c.txt")); + assertEquals(10, FilenameUtils.getPrefixLength("\\\\server.\\a\\b\\c.txt")); + + assertEquals(-1, FilenameUtils.getPrefixLength("\\\\-server\\a\\b\\c.txt")); + assertEquals(-1, FilenameUtils.getPrefixLength("\\\\.\\a\\b\\c.txt")); + assertEquals(-1, FilenameUtils.getPrefixLength("\\\\..\\a\\b\\c.txt")); + + } public void testIndexOfLastSeparator() { assertEquals(-1, FilenameUtils.indexOfLastSeparator(null));
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor