summaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/dirent_uri.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/dirent_uri.c')
-rw-r--r--subversion/libsvn_subr/dirent_uri.c237
1 files changed, 147 insertions, 90 deletions
diff --git a/subversion/libsvn_subr/dirent_uri.c b/subversion/libsvn_subr/dirent_uri.c
index d2a93db..6886a3e 100644
--- a/subversion/libsvn_subr/dirent_uri.c
+++ b/subversion/libsvn_subr/dirent_uri.c
@@ -38,6 +38,7 @@
#include "dirent_uri.h"
#include "private/svn_fspath.h"
+#include "private/svn_cert.h"
/* The canonical empty path. Can this be changed? Well, change the empty
test below and the path library will work, not so sure about the fs/wc
@@ -104,7 +105,7 @@ canonicalize_to_lower(char c)
if (c < 'A' || c > 'Z')
return c;
else
- return c - 'A' + 'a';
+ return (char)(c - 'A' + 'a');
}
/* Locale insensitive toupper() for converting parts of dirents and urls
@@ -115,7 +116,7 @@ canonicalize_to_upper(char c)
if (c < 'a' || c > 'z')
return c;
else
- return c - 'a' + 'A';
+ return (char)(c - 'a' + 'A');
}
/* Calculates the length of the dirent absolute or non absolute root in
@@ -359,8 +360,24 @@ canonicalize(path_type_t type, const char *path, apr_pool_t *pool)
src = seg;
/* Found a hostname, convert to lowercase and copy to dst. */
- while (*src && (*src != '/') && (*src != ':'))
- *(dst++) = canonicalize_to_lower((*src++));
+ if (*src == '[')
+ {
+ *(dst++) = *(src++); /* Copy '[' */
+
+ while (*src == ':'
+ || (*src >= '0' && (*src <= '9'))
+ || (*src >= 'a' && (*src <= 'f'))
+ || (*src >= 'A' && (*src <= 'F')))
+ {
+ *(dst++) = canonicalize_to_lower((*src++));
+ }
+
+ if (*src == ']')
+ *(dst++) = *(src++); /* Copy ']' */
+ }
+ else
+ while (*src && (*src != '/') && (*src != ':'))
+ *(dst++) = canonicalize_to_lower((*src++));
if (*src == ':')
{
@@ -884,10 +901,10 @@ svn_dirent_local_style(const char *dirent, apr_pool_t *pool)
}
const char *
-svn_relpath__internal_style(const char *dirent,
- apr_pool_t *pool)
+svn_relpath__internal_style(const char *relpath,
+ apr_pool_t *pool)
{
- return svn_relpath_canonicalize(internal_style(dirent, pool), pool);
+ return svn_relpath_canonicalize(internal_style(relpath, pool), pool);
}
@@ -911,7 +928,7 @@ svn_dirent_is_root(const char *dirent, apr_size_t len)
&& dirent[len - 1] != '/')
{
int segments = 0;
- int i;
+ apr_size_t i;
for (i = len; i >= 2; i--)
{
if (dirent[i] == '/')
@@ -1295,25 +1312,17 @@ svn_uri_basename(const char *uri, apr_pool_t *pool)
{
apr_size_t len = strlen(uri);
apr_size_t start;
- const char *base_name;
assert(svn_uri_is_canonical(uri, NULL));
if (svn_uri_is_root(uri, len))
return "";
- else
- {
- start = len;
- while (start > 0 && uri[start - 1] != '/')
- --start;
- }
- if (pool)
- base_name = apr_pstrmemdup(pool, uri + start, len - start);
- else
- base_name = uri + start;
+ start = len;
+ while (start > 0 && uri[start - 1] != '/')
+ --start;
- return svn_path_uri_decode(base_name, pool);
+ return svn_path_uri_decode(uri + start, pool);
}
void
@@ -1403,41 +1412,13 @@ svn_dirent_is_child(const char *parent_dirent,
}
const char *
-svn_relpath__is_child(const char *parent_relpath,
- const char *child_relpath,
- apr_pool_t *pool)
-{
- /* assert(relpath_is_canonical(parent_relpath)); */
- /* assert(relpath_is_canonical(child_relpath)); */
-
- return is_child(type_relpath, parent_relpath, child_relpath, pool);
-}
-
-const char *
-svn_uri__is_child(const char *parent_uri,
- const char *child_uri,
- apr_pool_t *pool)
-{
- const char *relpath;
-
- assert(pool); /* hysterical raisins. */
- assert(svn_uri_is_canonical(parent_uri, NULL));
- assert(svn_uri_is_canonical(child_uri, NULL));
-
- relpath = is_child(type_uri, parent_uri, child_uri, pool);
- if (relpath)
- relpath = svn_path_uri_decode(relpath, pool);
- return relpath;
-}
-
-const char *
svn_dirent_skip_ancestor(const char *parent_dirent,
const char *child_dirent)
{
apr_size_t len = strlen(parent_dirent);
apr_size_t root_len;
- if (0 != memcmp(parent_dirent, child_dirent, len))
+ if (0 != strncmp(parent_dirent, child_dirent, len))
return NULL; /* parent_dirent is no ancestor of child_dirent */
if (child_dirent[len] == 0)
@@ -1495,7 +1476,7 @@ svn_relpath_skip_ancestor(const char *parent_relpath,
if (len == 0)
return child_relpath;
- if (0 != memcmp(parent_relpath, child_relpath, len))
+ if (0 != strncmp(parent_relpath, child_relpath, len))
return NULL; /* parent_relpath is no ancestor of child_relpath */
if (child_relpath[len] == 0)
@@ -1518,7 +1499,7 @@ uri_skip_ancestor(const char *parent_uri,
assert(svn_uri_is_canonical(parent_uri, NULL));
assert(svn_uri_is_canonical(child_uri, NULL));
- if (0 != memcmp(parent_uri, child_uri, len))
+ if (0 != strncmp(parent_uri, child_uri, len))
return NULL; /* parent_uri is no ancestor of child_uri */
if (child_uri[len] == 0)
@@ -1547,12 +1528,6 @@ svn_dirent_is_ancestor(const char *parent_dirent, const char *child_dirent)
}
svn_boolean_t
-svn_relpath__is_ancestor(const char *parent_relpath, const char *child_relpath)
-{
- return svn_relpath_skip_ancestor(parent_relpath, child_relpath) != NULL;
-}
-
-svn_boolean_t
svn_uri__is_ancestor(const char *parent_uri, const char *child_uri)
{
return uri_skip_ancestor(parent_uri, child_uri) != NULL;
@@ -1675,7 +1650,7 @@ svn_dirent_canonicalize(const char *dirent, apr_pool_t *pool)
}
svn_boolean_t
-svn_dirent_is_canonical(const char *dirent, apr_pool_t *pool)
+svn_dirent_is_canonical(const char *dirent, apr_pool_t *scratch_pool)
{
const char *ptr = dirent;
if (*ptr == '/')
@@ -1688,7 +1663,8 @@ svn_dirent_is_canonical(const char *dirent, apr_pool_t *pool)
/* TODO: Scan hostname and sharename and fall back to part code */
/* ### Fall back to old implementation */
- return (strcmp(dirent, svn_dirent_canonicalize(dirent, pool)) == 0);
+ return (strcmp(dirent, svn_dirent_canonicalize(dirent, scratch_pool))
+ == 0);
}
#endif /* SVN_USE_DOS_PATHS */
}
@@ -1762,7 +1738,7 @@ svn_relpath_is_canonical(const char *relpath)
}
svn_boolean_t
-svn_uri_is_canonical(const char *uri, apr_pool_t *pool)
+svn_uri_is_canonical(const char *uri, apr_pool_t *scratch_pool)
{
const char *ptr = uri, *seg = uri;
const char *schema_data = NULL;
@@ -1815,12 +1791,28 @@ svn_uri_is_canonical(const char *uri, apr_pool_t *pool)
/* Found a hostname, check that it's all lowercase. */
ptr = seg;
- while (*ptr && *ptr != '/' && *ptr != ':')
+
+ if (*ptr == '[')
{
- if (*ptr >= 'A' && *ptr <= 'Z')
+ ptr++;
+ while (*ptr == ':'
+ || (*ptr >= '0' && *ptr <= '9')
+ || (*ptr >= 'a' && *ptr <= 'f'))
+ {
+ ptr++;
+ }
+
+ if (*ptr != ']')
return FALSE;
ptr++;
}
+ else
+ while (*ptr && *ptr != '/' && *ptr != ':')
+ {
+ if (*ptr >= 'A' && *ptr <= 'Z')
+ return FALSE;
+ ptr++;
+ }
/* Found a portnumber */
if (*ptr == ':')
@@ -1866,6 +1858,9 @@ svn_uri_is_canonical(const char *uri, apr_pool_t *pool)
#endif /* SVN_USE_DOS_PATHS */
/* Now validate the rest of the URI. */
+ seg = ptr;
+ while (*ptr && (*ptr != '/'))
+ ptr++;
while(1)
{
apr_size_t seglen = ptr - seg;
@@ -1884,9 +1879,8 @@ svn_uri_is_canonical(const char *uri, apr_pool_t *pool)
if (*ptr == '/')
ptr++;
- seg = ptr;
-
+ seg = ptr;
while (*ptr && (*ptr != '/'))
ptr++;
}
@@ -2443,7 +2437,17 @@ svn_uri_get_file_url_from_dirent(const char **url,
*url = apr_pstrcat(pool, "file:", dirent, NULL);
}
else
- *url = apr_pstrcat(pool, "file:///", dirent, NULL);
+ {
+ char *uri = apr_pstrcat(pool, "file:///", dirent, NULL);
+ apr_size_t len = 8 /* strlen("file:///") */ + strlen(dirent);
+
+ /* "C:/" is a canonical dirent on Windows,
+ but "file:///C:/" is not a canonical uri */
+ if (uri[len-1] == '/')
+ uri[len-1] = '\0';
+
+ *url = uri;
+ }
#endif
return SVN_NO_ERROR;
@@ -2481,21 +2485,6 @@ svn_fspath__is_root(const char *fspath, apr_size_t len)
const char *
-svn_fspath__is_child(const char *parent_fspath,
- const char *child_fspath,
- apr_pool_t *pool)
-{
- const char *result;
- assert(svn_fspath__is_canonical(parent_fspath));
- assert(svn_fspath__is_canonical(child_fspath));
-
- result = svn_relpath__is_child(parent_fspath + 1, child_fspath + 1, pool);
-
- assert(result == NULL || svn_relpath_is_canonical(result));
- return result;
-}
-
-const char *
svn_fspath__skip_ancestor(const char *parent_fspath,
const char *child_fspath)
{
@@ -2505,16 +2494,6 @@ svn_fspath__skip_ancestor(const char *parent_fspath,
return svn_relpath_skip_ancestor(parent_fspath + 1, child_fspath + 1);
}
-svn_boolean_t
-svn_fspath__is_ancestor(const char *parent_fspath,
- const char *child_fspath)
-{
- assert(svn_fspath__is_canonical(parent_fspath));
- assert(svn_fspath__is_canonical(child_fspath));
-
- return svn_relpath__is_ancestor(parent_fspath + 1, child_fspath + 1);
-}
-
const char *
svn_fspath__dirname(const char *fspath,
@@ -2619,3 +2598,81 @@ svn_urlpath__canonicalize(const char *uri,
}
return uri;
}
+
+
+/* -------------- The cert API (see private/svn_cert.h) ------------- */
+
+svn_boolean_t
+svn_cert__match_dns_identity(svn_string_t *pattern, svn_string_t *hostname)
+{
+ apr_size_t pattern_pos = 0, hostname_pos = 0;
+
+ /* support leading wildcards that composed of the only character in the
+ * left-most label. */
+ if (pattern->len >= 2 &&
+ pattern->data[pattern_pos] == '*' &&
+ pattern->data[pattern_pos + 1] == '.')
+ {
+ while (hostname_pos < hostname->len &&
+ hostname->data[hostname_pos] != '.')
+ {
+ hostname_pos++;
+ }
+ /* Assume that the wildcard must match something. Rule 2 says
+ * that *.example.com should not match example.com. If the wildcard
+ * ends up not matching anything then it matches .example.com which
+ * seems to be essentially the same as just example.com */
+ if (hostname_pos == 0)
+ return FALSE;
+
+ pattern_pos++;
+ }
+
+ while (pattern_pos < pattern->len && hostname_pos < hostname->len)
+ {
+ char pattern_c = pattern->data[pattern_pos];
+ char hostname_c = hostname->data[hostname_pos];
+
+ /* fold case as described in RFC 4343.
+ * Note: We actually convert to lowercase, since our URI
+ * canonicalization code converts to lowercase and generally
+ * most certs are issued with lowercase DNS names, meaning
+ * this avoids the fold operation in most cases. The RFC
+ * suggests the opposite transformation, but doesn't require
+ * any specific implementation in any case. It is critical
+ * that this folding be locale independent so you can't use
+ * tolower(). */
+ pattern_c = canonicalize_to_lower(pattern_c);
+ hostname_c = canonicalize_to_lower(hostname_c);
+
+ if (pattern_c != hostname_c)
+ {
+ /* doesn't match */
+ return FALSE;
+ }
+ else
+ {
+ /* characters match so skip both */
+ pattern_pos++;
+ hostname_pos++;
+ }
+ }
+
+ /* ignore a trailing period on the hostname since this has no effect on the
+ * security of the matching. See the following for the long explanation as
+ * to why:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=134402#c28
+ */
+ if (pattern_pos == pattern->len &&
+ hostname_pos == hostname->len - 1 &&
+ hostname->data[hostname_pos] == '.')
+ hostname_pos++;
+
+ if (pattern_pos != pattern->len || hostname_pos != hostname->len)
+ {
+ /* end didn't match */
+ return FALSE;
+ }
+
+ return TRUE;
+}