diff options
Diffstat (limited to 'subversion/svnserve/serve.c')
-rw-r--r-- | subversion/svnserve/serve.c | 295 |
1 files changed, 201 insertions, 94 deletions
diff --git a/subversion/svnserve/serve.c b/subversion/svnserve/serve.c index 1fe27b2..06b58f8 100644 --- a/subversion/svnserve/serve.c +++ b/subversion/svnserve/serve.c @@ -107,15 +107,22 @@ typedef struct authz_baton_t { svn_ra_svn_conn_t *conn; } authz_baton_t; -/* svn_error_create() a new error, log_server_error() it, and - return it. */ +/* Log an error. */ static void -log_error(svn_error_t *err, server_baton_t *server) +log_error(const svn_error_t *err, server_baton_t *server) { logger__log_error(server->logger, err, server->repository, server->client_info); } +/* Log a warning. */ +static void +log_warning(const svn_error_t *err, server_baton_t *server) +{ + logger__log_warning(server->logger, err, server->repository, + server->client_info); +} + /* svn_error_create() a new error, log_server_error() it, and return it. */ static svn_error_t * @@ -264,17 +271,23 @@ canonicalize_access_file(const char **access_file, repository_t *repository, { if (svn_path_is_url(*access_file)) { - *access_file = svn_uri_canonicalize(*access_file, pool); + const char *canonical_url; + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, *access_file, + pool, pool)); + *access_file = canonical_url; } else if (svn_path_is_repos_relative_url(*access_file)) { const char *repos_root_url; + const char *canonical_url; SVN_ERR(svn_uri_get_file_url_from_dirent(&repos_root_url, repos_root, pool)); SVN_ERR(svn_path_resolve_repos_relative_url(access_file, *access_file, repos_root_url, pool)); - *access_file = svn_uri_canonicalize(*access_file, pool); + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, *access_file, + pool, pool)); + *access_file = canonical_url; } else { @@ -294,7 +307,10 @@ static svn_error_t * load_authz_config(repository_t *repository, const char *repos_root, svn_config_t *cfg, - apr_pool_t *pool) + svn_repos_authz_warning_func_t warning_func, + void *warning_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { const char *authzdb_path; const char *groupsdb_path; @@ -313,17 +329,18 @@ load_authz_config(repository_t *repository, /* Canonicalize and add the base onto the authzdb_path (if needed). */ err = canonicalize_access_file(&authzdb_path, repository, - repos_root, pool); + repos_root, scratch_pool); /* Same for the groupsdb_path if it is present. */ if (groupsdb_path && !err) err = canonicalize_access_file(&groupsdb_path, repository, - repos_root, pool); + repos_root, scratch_pool); if (!err) - err = svn_repos_authz_read3(&repository->authzdb, authzdb_path, + err = svn_repos_authz_read4(&repository->authzdb, authzdb_path, groupsdb_path, TRUE, repository->repos, - pool, pool); + warning_func, warning_baton, + result_pool, scratch_pool); if (err) return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, err, NULL); @@ -369,7 +386,7 @@ handle_config_error(svn_error_t *error, /* Now that we've logged the error, clear it and return a * nice, generic error to the user: - * http://subversion.tigris.org/issues/show_bug.cgi?id=2271 */ + * https://issues.apache.org/jira/browse/SVN-2271 */ svn_error_clear(error); return svn_error_create(apr_err, NULL, NULL); } @@ -843,7 +860,7 @@ static svn_error_t *set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; - const char *path, *lock_token, *depth_word; + const char *path, *lock_token, *depth_word, *canonical_relpath; svn_revnum_t rev; /* Default to infinity, for old clients that don't send depth. */ svn_depth_t depth = svn_depth_infinity; @@ -854,7 +871,9 @@ static svn_error_t *set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, &depth_word)); if (depth_word) depth = svn_depth_from_word(depth_word); - path = svn_relpath_canonicalize(path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_relpath, NULL, path, + pool, pool)); + path = canonical_relpath; if (b->from_rev && strcmp(path, "") == 0) *b->from_rev = rev; if (!b->err) @@ -870,10 +889,12 @@ static svn_error_t *delete_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; - const char *path; + const char *path, *canonical_relpath; SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &path)); - path = svn_relpath_canonicalize(path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_relpath, NULL, path, + pool, pool)); + path = canonical_relpath; if (!b->err) b->err = svn_repos_delete_path(b->report_baton, path, pool); return SVN_NO_ERROR; @@ -883,7 +904,8 @@ static svn_error_t *link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; - const char *path, *url, *lock_token, *fs_path, *depth_word; + const char *path, *url, *lock_token, *fs_path, *depth_word, *canonical_url; + const char *canonical_path; svn_revnum_t rev; svn_boolean_t start_empty; /* Default to infinity, for old clients that don't send depth. */ @@ -895,8 +917,12 @@ static svn_error_t *link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, /* ### WHAT?! The link path is an absolute URL?! Didn't see that coming... -- cmpilato */ - path = svn_relpath_canonicalize(path, pool); - url = svn_uri_canonicalize(url, pool); + + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); + path = canonical_path; + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, url, pool, pool)); + url = canonical_url; if (depth_word) depth = svn_depth_from_word(depth_word); if (!b->err) @@ -1112,11 +1138,12 @@ reparent(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *url; + const char *url, *canonical_url; const char *fs_path; SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &url)); - url = svn_uri_canonicalize(url, pool); + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, url, pool, pool)); + url = canonical_url; SVN_ERR(trivial_auth_request(conn, pool, b)); SVN_CMD_ERR(get_fs_path(svn_path_uri_decode(b->repository->repos_url, pool), svn_path_uri_decode(url, pool), @@ -1335,6 +1362,7 @@ add_lock_tokens(const svn_ra_svn__list_t *lock_tokens, server_baton_t *sb, apr_pool_t *pool) { + const char *canonical_path; int i; svn_fs_access_t *fs_access; @@ -1364,9 +1392,10 @@ add_lock_tokens(const svn_ra_svn__list_t *lock_tokens, "Lock token isn't a string"); path = path_item->u.string.data; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(sb->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), - pool); + canonical_path, pool); if (! lookup_access(pool, sb, svn_authz_write, full_path, TRUE)) return error_create_and_log(SVN_ERR_RA_NOT_AUTHORIZED, NULL, NULL, @@ -1404,6 +1433,7 @@ unlock_paths(const svn_ra_svn__list_t *lock_tokens, int i; apr_pool_t *subpool = svn_pool_create(pool); apr_hash_t *targets = apr_hash_make(subpool); + const char *canonical_path; svn_error_t *err; for (i = 0; i < lock_tokens->nelts; ++i) @@ -1416,9 +1446,10 @@ unlock_paths(const svn_ra_svn__list_t *lock_tokens, token_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 1); path = path_item->u.string.data; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(sb->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - subpool); + canonical_path, subpool); token = token_item->u.string.data; svn_hash_sets(targets, full_path, token); } @@ -1558,7 +1589,7 @@ get_file(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *full_path, *hex_digest; + const char *path, *full_path, *hex_digest, *canonical_path; svn_revnum_t rev; svn_fs_root_t *root; svn_stream_t *contents; @@ -1585,8 +1616,10 @@ get_file(svn_ra_svn_conn_t *conn, if (wants_inherited_props == SVN_RA_SVN_UNSPECIFIED_NUMBER) wants_inherited_props = FALSE; - full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, pool, + pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, canonical_path, + pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, @@ -1743,7 +1776,7 @@ get_dir(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t rev; apr_hash_t *entries, *props = NULL; apr_array_header_t *inherited_props; @@ -1769,8 +1802,10 @@ get_dir(svn_ra_svn_conn_t *conn, wants_inherited_props = FALSE; SVN_ERR(parse_dirent_fields(&dirent_fields, dirent_fields_list)); - full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, canonical_path, + pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, @@ -1917,7 +1952,7 @@ update(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *target, *full_path, *depth_word; + const char *target, *full_path, *depth_word, *canonical_target; svn_boolean_t recurse; svn_tristate_t send_copyfrom_args; /* Optional; default FALSE */ svn_tristate_t ignore_ancestry; /* Optional; default FALSE */ @@ -1930,7 +1965,9 @@ update(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cb?w3?3", &rev, &target, &recurse, &depth_word, &send_copyfrom_args, &ignore_ancestry)); - target = svn_relpath_canonicalize(target, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_target, NULL, target, + pool, pool)); + target = canonical_target; if (depth_word) depth = svn_depth_from_word(depth_word); @@ -1976,7 +2013,7 @@ switch_cmd(svn_ra_svn_conn_t *conn, server_baton_t *b = baton; svn_revnum_t rev; const char *target, *depth_word; - const char *switch_url, *switch_path; + const char *switch_url, *switch_path, *canonical_url, *canonical_target; svn_boolean_t recurse; /* Default to unknown. Old clients won't send depth, but we'll handle that by converting recurse if necessary. */ @@ -1988,9 +2025,12 @@ switch_cmd(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cbc?w?33", &rev, &target, &recurse, &switch_url, &depth_word, &send_copyfrom_args, &ignore_ancestry)); - target = svn_relpath_canonicalize(target, pool); - switch_url = svn_uri_canonicalize(switch_url, pool); - + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_target, NULL, target, + pool, pool)); + target = canonical_target; + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, switch_url, pool, + pool)); + switch_url = canonical_url; if (depth_word) depth = svn_depth_from_word(depth_word); else @@ -2028,7 +2068,7 @@ status(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *target, *depth_word; + const char *target, *depth_word, *canonical_target; svn_boolean_t recurse; /* Default to unknown. Old clients won't send depth, but we'll handle that by converting recurse if necessary. */ @@ -2037,7 +2077,9 @@ status(svn_ra_svn_conn_t *conn, /* Parse the arguments. */ SVN_ERR(svn_ra_svn__parse_tuple(params, "cb?(?r)?w", &target, &recurse, &rev, &depth_word)); - target = svn_relpath_canonicalize(target, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_target, NULL, target, + pool, pool)); + target = canonical_target; if (depth_word) depth = svn_depth_from_word(depth_word); @@ -2067,7 +2109,8 @@ diff(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *target, *versus_url, *versus_path, *depth_word; + const char *target, *versus_url, *versus_path, *depth_word, *canonical_url; + const char *canonical_target; svn_boolean_t recurse, ignore_ancestry; svn_boolean_t text_deltas; /* Default to unknown. Old clients won't send depth, but we'll @@ -2090,8 +2133,12 @@ diff(svn_ra_svn_conn_t *conn, &ignore_ancestry, &versus_url, &text_deltas, &depth_word)); } - target = svn_relpath_canonicalize(target, pool); - versus_url = svn_uri_canonicalize(versus_url, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_target, NULL, target, + pool, pool)); + target = canonical_target; + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, versus_url, + pool, pool)); + versus_url = canonical_url; if (depth_word) depth = svn_depth_from_word(depth_word); @@ -2216,13 +2263,15 @@ get_mergeinfo(svn_ra_svn_conn_t *conn, for (i = 0; i < paths->nelts; i++) { svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(paths, i); - const char *full_path; + const char *full_path, *canonical_path; if (item->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Path is not a string")); - full_path = svn_relpath_canonicalize(item->u.string.data, pool); - full_path = svn_fspath__join(b->repository->fs_path->data, full_path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, + item->u.string.data, pool, pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, + canonical_path, pool); APR_ARRAY_PUSH(canonical_paths, const char *) = full_path; } @@ -2384,7 +2433,7 @@ log_cmd(svn_ra_svn_conn_t *conn, svn_error_t *err, *write_err; server_baton_t *b = baton; svn_revnum_t start_rev, end_rev; - const char *full_path; + const char *full_path, *canonical_path; svn_boolean_t send_changed_paths, strict_node, include_merged_revisions; apr_array_header_t *full_paths, *revprops; svn_ra_svn__list_t *paths, *revprop_items; @@ -2448,9 +2497,10 @@ log_cmd(svn_ra_svn_conn_t *conn, if (elt->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Log path entry not a string")); - full_path = svn_relpath_canonicalize(elt->u.string.data, pool), - full_path = svn_fspath__join(b->repository->fs_path->data, full_path, - pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, + elt->u.string.data, pool, pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, + canonical_path, pool); APR_ARRAY_PUSH(full_paths, const char *) = full_path; } SVN_ERR(trivial_auth_request(conn, pool, b)); @@ -2493,13 +2543,15 @@ check_path(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_fs_root_t *root; svn_node_kind_t kind; SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool));; full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, @@ -2526,13 +2578,15 @@ stat_cmd(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *path, *full_path, *cdate; + const char *path, *full_path, *cdate, *canonical_path; svn_fs_root_t *root; svn_dirent_t *dirent; SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev)); - full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, pool, + pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, canonical_path, + pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, @@ -2581,7 +2635,7 @@ get_locations(svn_ra_svn_conn_t *conn, svn_ra_svn__list_t *loc_revs_proto; svn_ra_svn__item_t *elt; int i; - const char *relative_path; + const char *relative_path, *canonical_path; svn_revnum_t peg_revision; apr_hash_t *fs_locations; const char *abs_path; @@ -2594,7 +2648,9 @@ get_locations(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(params, "crl", &relative_path, &peg_revision, &loc_revs_proto)); - relative_path = svn_relpath_canonicalize(relative_path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, relative_path, + pool, pool)); + relative_path = canonical_path; abs_path = svn_fspath__join(b->repository->fs_path->data, relative_path, pool); @@ -2680,7 +2736,7 @@ get_location_segments(svn_ra_svn_conn_t *conn, svn_error_t *err, *write_err; server_baton_t *b = baton; svn_revnum_t peg_revision, start_rev, end_rev; - const char *relative_path; + const char *relative_path, *canonical_path; const char *abs_path; authz_baton_t ab; @@ -2691,7 +2747,9 @@ get_location_segments(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)(?r)(?r)", &relative_path, &peg_revision, &start_rev, &end_rev)); - relative_path = svn_relpath_canonicalize(relative_path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, relative_path, + pool, pool)); + relative_path = canonical_path; abs_path = svn_fspath__join(b->repository->fs_path->data, relative_path, pool); @@ -2843,6 +2901,7 @@ get_file_revs(svn_ra_svn_conn_t *conn, svn_revnum_t start_rev, end_rev; const char *path; const char *full_path; + const char *canonical_path; apr_uint64_t include_merged_revs_param; svn_boolean_t include_merged_revisions; authz_baton_t ab; @@ -2854,7 +2913,9 @@ get_file_revs(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)(?r)?B", &path, &start_rev, &end_rev, &include_merged_revs_param)); - path = svn_relpath_canonicalize(path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); + path = canonical_path; SVN_ERR(trivial_auth_request(conn, pool, b)); full_path = svn_fspath__join(b->repository->fs_path->data, path, pool); @@ -2897,14 +2958,17 @@ lock(svn_ra_svn_conn_t *conn, const char *path; const char *comment; const char *full_path; + const char *canonical_path; svn_boolean_t steal_lock; svn_revnum_t current_rev; svn_lock_t *l; SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?c)b(?r)", &path, &comment, &steal_lock, ¤t_rev)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool));; full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, full_path, TRUE)); @@ -2996,7 +3060,7 @@ lock_many(svn_ra_svn_conn_t *conn, /* Parse the lock requests from PATH_REVS into TARGETS. */ for (i = 0; i < path_revs->nelts; ++i) { - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t current_rev; svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(path_revs, i); svn_fs_lock_target_t *target; @@ -3010,9 +3074,10 @@ lock_many(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "c(?r)", &path, ¤t_rev)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - pool); + canonical_path, pool); target = svn_fs_lock_target_create(NULL, current_rev, pool); /* Any duplicate paths, once canonicalized, get collapsed into a @@ -3059,7 +3124,7 @@ lock_many(svn_ra_svn_conn_t *conn, /* Return results in the same order as the paths were supplied. */ for (i = 0; i < path_revs->nelts; ++i) { - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t current_rev; svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(path_revs, i); struct lock_result_t *result; @@ -3071,9 +3136,10 @@ lock_many(svn_ra_svn_conn_t *conn, if (write_err) break; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - subpool); + canonical_path, subpool); result = svn_hash_gets(lmb.results, full_path); if (!result) @@ -3128,14 +3194,16 @@ unlock(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *token, *full_path; + const char *path, *token, *full_path, *canonical_path; svn_boolean_t break_lock; SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?c)b", &path, &token, &break_lock)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); /* Username required unless break_lock was specified. */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, @@ -3179,7 +3247,7 @@ unlock_many(svn_ra_svn_conn_t *conn, for (i = 0; i < unlock_tokens->nelts; i++) { svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(unlock_tokens, i); - const char *path, *full_path, *token; + const char *path, *full_path, *token, *canonical_path; svn_pool_clear(subpool); @@ -3192,9 +3260,10 @@ unlock_many(svn_ra_svn_conn_t *conn, if (!token) token = ""; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - pool); + canonical_path, pool); /* Any duplicate paths, once canonicalized, get collapsed into a single path that is processed once. The result is then @@ -3239,7 +3308,7 @@ unlock_many(svn_ra_svn_conn_t *conn, /* Return results in the same order as the paths were supplied. */ for (i = 0; i < unlock_tokens->nelts; ++i) { - const char *path, *token, *full_path; + const char *path, *token, *full_path, *canonical_path; svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(unlock_tokens, i); struct lock_result_t *result; @@ -3250,9 +3319,10 @@ unlock_many(svn_ra_svn_conn_t *conn, if (write_err) break; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - pool); + canonical_path, pool); result = svn_hash_gets(lmb.results, full_path); if (!result) @@ -3302,12 +3372,15 @@ get_lock(svn_ra_svn_conn_t *conn, server_baton_t *b = baton; const char *path; const char *full_path; + const char *canonical_path; svn_lock_t *l; SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &path)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, full_path, FALSE)); @@ -3333,6 +3406,7 @@ get_locks(svn_ra_svn_conn_t *conn, server_baton_t *b = baton; const char *path; const char *full_path; + const char *canonical_path; const char *depth_word; svn_depth_t depth; apr_hash_t *locks; @@ -3356,8 +3430,10 @@ get_locks(svn_ra_svn_conn_t *conn, return log_fail_and_flush(err, b, conn, pool); } + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); SVN_ERR(trivial_auth_request(conn, pool, b)); @@ -3494,15 +3570,17 @@ get_deleted_rev(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t peg_revision; svn_revnum_t end_revision; svn_revnum_t revision_deleted; SVN_ERR(svn_ra_svn__parse_tuple(params, "crr", &path, &peg_revision, &end_revision)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); SVN_ERR(log_command(b, conn, pool, "get-deleted-rev")); SVN_ERR(trivial_auth_request(conn, pool, b)); SVN_CMD_ERR(svn_repos_deleted_rev(b->repository->fs, full_path, peg_revision, @@ -3531,7 +3609,7 @@ get_inherited_props(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t rev; svn_fs_root_t *root; apr_array_header_t *inherited_props; @@ -3546,9 +3624,10 @@ get_inherited_props(svn_ra_svn_conn_t *conn, /* Parse arguments. */ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + iterpool, iterpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, iterpool), - pool); + canonical_path, pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, iterpool, b, svn_authz_read, @@ -3621,7 +3700,7 @@ list(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t rev; svn_depth_t depth; apr_array_header_t *patterns = NULL; @@ -3647,8 +3726,10 @@ list(svn_ra_svn_conn_t *conn, SVN_ERR(parse_dirent_fields(&rb.dirent_fields, dirent_fields_list)); depth = svn_depth_from_word(depth_word); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); /* Read the patterns list. */ if (patterns_list) @@ -3806,10 +3887,13 @@ find_repos(const char *url, repository_t *repository, svn_repos__config_pool_t *config_pool, apr_hash_t *fs_config, + svn_repos_authz_warning_func_t authz_warning_func, + void *authz_warning_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - const char *path, *full_path, *fs_path, *hooks_env; + const char *path, *full_path, *fs_path, *hooks_env, *canonical_path; + const char *canonical_root; svn_stringbuf_t *url_buf; svn_boolean_t sasl_requested; @@ -3825,8 +3909,9 @@ find_repos(const char *url, if (path == NULL) path = ""; } - path = svn_relpath_canonicalize(path, scratch_pool); - path = svn_path_uri_decode(path, scratch_pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + scratch_pool, scratch_pool)); + path = svn_path_uri_decode(canonical_path, scratch_pool); /* Ensure that it isn't possible to escape the root by disallowing '..' segments. */ @@ -3835,8 +3920,9 @@ find_repos(const char *url, "Couldn't determine repository path"); /* Join the server-configured root with the client path. */ - full_path = svn_dirent_join(svn_dirent_canonicalize(root, scratch_pool), - path, scratch_pool); + SVN_ERR(svn_dirent_canonicalize_safe(&canonical_root, NULL, root, + scratch_pool, scratch_pool)); + full_path = svn_dirent_join(canonical_root, path, scratch_pool); /* Search for a repository in the full path. */ repository->repos_root = svn_repos_find_root_path(full_path, result_pool); @@ -3857,7 +3943,7 @@ find_repos(const char *url, svn_path_remove_components(url_buf, svn_path_component_count(repository->fs_path->data)); repository->repos_url = url_buf->data; - repository->authz_repos_name = svn_dirent_is_child(root, + repository->authz_repos_name = svn_dirent_is_child(canonical_root, repository->repos_root, result_pool); if (repository->authz_repos_name == NULL) @@ -3883,7 +3969,8 @@ find_repos(const char *url, SVN_ERR(load_pwdb_config(repository, cfg, config_pool, result_pool)); SVN_ERR(load_authz_config(repository, repository->repos_root, cfg, - result_pool)); + authz_warning_func, authz_warning_baton, + result_pool, scratch_pool)); /* Should we use Cyrus SASL? */ SVN_ERR(svn_config_get_bool(cfg, &sasl_requested, @@ -4105,6 +4192,16 @@ get_client_info(svn_ra_svn_conn_t *conn, return client_info; } +static void +handle_authz_warning(void *baton, + const svn_error_t *err, + apr_pool_t *scratch_pool) +{ + server_baton_t *const server_baton = baton; + log_warning(err, server_baton); + SVN_UNUSED(scratch_pool); +} + /* Construct the server baton for CONN using PARAMS and return it in *BATON. * It's lifetime is the same as that of CONN. SCRATCH_POOL */ @@ -4116,7 +4213,7 @@ construct_server_baton(server_baton_t **baton, { svn_error_t *err; apr_uint64_t ver; - const char *client_url, *ra_client_string, *client_string; + const char *client_url, *ra_client_string, *client_string, *canonical_url; svn_ra_svn__list_t *caplist; apr_pool_t *conn_pool = svn_ra_svn__get_pool(conn); server_baton_t *b = apr_pcalloc(conn_pool, sizeof(*b)); @@ -4183,15 +4280,21 @@ construct_server_baton(server_baton_t **baton, &ra_client_string, &client_string)); if (ver != 2) - return SVN_NO_ERROR; - - client_url = svn_uri_canonicalize(client_url, conn_pool); + return svn_error_createf(SVN_ERR_RA_SVN_BAD_VERSION, NULL, + "Unsupported ra_svn protocol version" + " %"APR_UINT64_T_FMT + " (supported versions: [2])", ver); + + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, client_url, + conn_pool, scratch_pool)); + client_url = canonical_url; SVN_ERR(svn_ra_svn__set_capabilities(conn, caplist)); /* All released versions of Subversion support edit-pipeline, * so we do not accept connections from clients that do not. */ if (! svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_EDIT_PIPELINE)) - return SVN_NO_ERROR; + return svn_error_create(SVN_ERR_RA_SVN_BAD_VERSION, NULL, + "Missing edit-pipeline capability"); /* find_repos needs the capabilities as a list of words (eventually they get handed to the start-commit hook). While we could add a @@ -4227,10 +4330,14 @@ construct_server_baton(server_baton_t **baton, } } + /* (*b) has the logger, repository and client_info set, so it can + be used as the authz_warning_baton that eventyally gets passed + to log_warning(). */ err = handle_config_error(find_repos(client_url, params->root, b->vhost, b->read_only, params->cfg, b->repository, params->config_pool, params->fs_config, + handle_authz_warning, b, conn_pool, scratch_pool), b); if (!err) |