You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2019/01/22 14:34:55 UTC
svn commit: r1851823 - in /subversion/trunk: subversion/include/
subversion/libsvn_repos/ subversion/mod_authz_svn/ subversion/svnserve/
subversion/tests/cmdline/ subversion/tests/libsvn_repos/ tools/server-side/
Author: brane
Date: Tue Jan 22 14:34:55 2019
New Revision: 1851823
URL: http://svn.apache.org/viewvc?rev=1851823&view=rev
Log:
Introduce a warning callback to the authz file parser API.
We need this to warn about the use of empty groups in authz files;
this is not an error and doesn't affect the authz file semantics,
but it's nice to be able to tell the user about it.
See issues #4794, #4802 and #4803.
* subversion/include/svn_repos.h
(svn_repos_authz_warning_func_t): New callback function type.
(svn_repos_authz_read4): New; API revision.
(svn_repos_authz_read3): Deprecated.
(svn_repos_authz_parse2): New; API revision.
(svn_repos_authz_parse): Deprecated.
* subversion/libsvn_repos/authz.h
(svn_authz__parse): Add warning function and baton parameters.
* subversion/libsvn_repos/authz.c
(authz_read): Add warning function and baton parameters.
Update calls to svn_authz__parse.
(svn_repos_authz_read4): Revised from svn_repos_authz_read3.
(svn_repos_authz_parse2): Revised from svn_repos_authz_parse.
* subversion/libsvn_repos/authz_parse.c
(struct ctor_baton_t): Add members warning_func and warning_baton.
(create_ctor_baton): Initialise these new members of the constructor baton.
(emit_parser_warning): New.
(SVN_AUTHZ_PARSE_WARN): New; wrapper macro for the above.
(array_insert_ace): Ignore and warn about the use of empty groups.
(svn_authz__parse): Update implementation to match prototype.
* subversion/libsvn_repos/deprecated.c
(svn_repos_authz_read3, svn_repos_authz_parse): Implement deprecated functions.
* subversion/mod_authz_svn/mod_authz_svn.c
(log_svn_message): New; replaces log_svn_error so that it's useful for
logging warnings as well.
(log_svn_error): Reimplement, calling log_svn_message.
(struct authz_warning_baton_t): New.
(log_authz_warning): New.
(get_access_conf): Set up an authz warning handler and baton, and call
svn_repos_authz_read4 instead of svn_repos_authz_read3.
* subversion/svnserve/logger.h
(logger__log_error): Make the 'err' parameter a pointer-to-const.
Update the docstring to say that the error is not cleared.
(logger__log_warning): New.
* subversion/svnserve/logger.c
(log_message): New; common base for logger__log_error and logger__log_message.
Also *do not* allocate 8k on the stack, use the logger pool, which gets
cleared at the end of the function.
(logger__log_error): Reimplement.
(logger__log_warning): Implement.
* subversion/svnserve/serve.c
(log_error): Make the error parameter const. Fix the docstring.
(log_warning): New.
(load_authz_config): Add warning function and baton parameters and fix pool
handling. Now calls svn_repos_authz_read4 instead of svn_repos_authz_read3.
(find_repos): Add warning function and baton parameters for load_authz_config.
(handle_authz_warning): New.
(construct_server_baton): Pass an authz warning handler and baton to find_repos.
* subversion/tests/cmdline/authz_tests.py
(group_member_empty_string): Fix docstring.
(empty_group): New test case.
(test_list): Run it.
* subversion/tests/cmdline/svnauthz_tests.py
(svnauthz_empty_group_test): Extend the @Issues decorator.
Add a check for the expected warning on stderr.
Modified:
subversion/trunk/subversion/include/svn_repos.h
subversion/trunk/subversion/libsvn_repos/authz.c
subversion/trunk/subversion/libsvn_repos/authz.h
subversion/trunk/subversion/libsvn_repos/authz_parse.c
subversion/trunk/subversion/libsvn_repos/deprecated.c
subversion/trunk/subversion/mod_authz_svn/mod_authz_svn.c
subversion/trunk/subversion/svnserve/logger.c
subversion/trunk/subversion/svnserve/logger.h
subversion/trunk/subversion/svnserve/serve.c
subversion/trunk/subversion/tests/cmdline/authz_tests.py
subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py
subversion/trunk/subversion/tests/libsvn_repos/authz-test.c
subversion/trunk/tools/server-side/svnauthz.c
Modified: subversion/trunk/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_repos.h?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_repos.h (original)
+++ subversion/trunk/subversion/include/svn_repos.h Tue Jan 22 14:34:55 2019
@@ -4147,6 +4147,19 @@ svn_error_t *
svn_repos_authz_initialize(apr_pool_t *pool);
/**
+ * Callback for reporting authz file parsing warnings.
+ *
+ * The implementation may use @a scratch_pool for temporary
+ * allocations but should not assume that the lifetime of that pool
+ * persists past the callback invocation.
+ *
+ * The implementation @e must @e not clear @a error.
+ */
+typedef void (*svn_repos_authz_warning_func_t)(void *baton,
+ const svn_error_t *error,
+ apr_pool_t *scratch_pool);
+
+/**
* Read authz configuration data from @a path (a dirent, an absolute file url
* or a registry path) into @a *authz_p, allocated in @a pool.
*
@@ -4164,8 +4177,31 @@ svn_repos_authz_initialize(apr_pool_t *p
* repository instance. Otherwise, set it to NULL and the repositories will
* be opened as needed.
*
+ * If the @a warning_func callback is not @c NULL, it is called
+ * (with @a warning_baton) to report non-fatal warnings emitted by
+ * the parser.
+ *
+ * @since New in 1.12.
+ */
+svn_error_t *
+svn_repos_authz_read4(svn_authz_t **authz_p,
+ const char *path,
+ const char *groups_path,
+ svn_boolean_t must_exist,
+ svn_repos_t *repos_hint,
+ svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Similar to svn_repos_authz_read3(), but with @a warning_func and
+ * @a warning_baton set to @c NULL.
+ *
* @since New in 1.10.
+ * @deprecated Provided for backward compatibility with the 1.11 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_repos_authz_read3(svn_authz_t **authz_p,
const char *path,
@@ -4206,12 +4242,35 @@ svn_repos_authz_read(svn_authz_t **authz
/**
* Read authz configuration data from @a stream into @a *authz_p,
- * allocated in @a pool.
+ * allocated in @a result_pool.
*
* If @a groups_stream is set, use the global groups parsed from it.
*
+ * If the @a warning_func callback is not @c NULL, it is called
+ * (with @a warning_baton) to report non-fatal warnings emitted by
+ * the parser.
+ *
+ * Uses @a scratch_pool for temporary aloocations.
+ *
+ * @since New in 1.12.
+ */
+svn_error_t *
+svn_repos_authz_parse2(svn_authz_t **authz_p,
+ svn_stream_t *stream,
+ svn_stream_t *groups_stream,
+ svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Similar to svn_repos_authz_parse2(), but with @a warning_func and
+ * @a warning_baton set to @c NULL.
+ *
* @since New in 1.8.
+ * @deprecated Provided for backward compatibility with the 1.11 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_repos_authz_parse(svn_authz_t **authz_p,
svn_stream_t *stream,
Modified: subversion/trunk/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/authz.c?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/authz.c (original)
+++ subversion/trunk/subversion/libsvn_repos/authz.c Tue Jan 22 14:34:55 2019
@@ -1548,6 +1548,8 @@ authz_read(authz_full_t **authz_p,
const char *groups_path,
svn_boolean_t must_exist,
svn_repos_t *repos_hint,
+ svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -1587,7 +1589,8 @@ authz_read(authz_full_t **authz_p,
/* Parse the configuration(s) and construct the full authz model
* from it. */
err = svn_authz__parse(authz_p, rules_stream, groups_stream,
- item_pool, scratch_pool);
+ warning_func, warning_baton,
+ item_pool, scratch_pool);
if (err != SVN_NO_ERROR)
{
/* That pool would otherwise never get destroyed. */
@@ -1611,11 +1614,11 @@ authz_read(authz_full_t **authz_p,
{
/* Parse the configuration(s) and construct the full authz model from
* it. */
- err = svn_error_quick_wrapf(svn_authz__parse(authz_p, rules_stream,
- groups_stream,
- result_pool, scratch_pool),
- "Error while parsing authz file: '%s':",
- path);
+ err = svn_error_quick_wrapf(
+ svn_authz__parse(authz_p, rules_stream, groups_stream,
+ warning_func, warning_baton,
+ result_pool, scratch_pool),
+ "Error while parsing authz file: '%s':", path);
}
svn_repos__destroy_config_access(config_access);
@@ -1628,11 +1631,13 @@ authz_read(authz_full_t **authz_p,
/*** Public functions. ***/
svn_error_t *
-svn_repos_authz_read3(svn_authz_t **authz_p,
+svn_repos_authz_read4(svn_authz_t **authz_p,
const char *path,
const char *groups_path,
svn_boolean_t must_exist,
svn_repos_t *repos_hint,
+ svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -1640,7 +1645,8 @@ svn_repos_authz_read3(svn_authz_t **auth
authz->pool = result_pool;
SVN_ERR(authz_read(&authz->full, &authz->authz_id, path, groups_path,
- must_exist, repos_hint, result_pool, scratch_pool));
+ must_exist, repos_hint, warning_func, warning_baton,
+ result_pool, scratch_pool));
*authz_p = authz;
return SVN_NO_ERROR;
@@ -1648,18 +1654,21 @@ svn_repos_authz_read3(svn_authz_t **auth
svn_error_t *
-svn_repos_authz_parse(svn_authz_t **authz_p, svn_stream_t *stream,
- svn_stream_t *groups_stream, apr_pool_t *pool)
+svn_repos_authz_parse2(svn_authz_t **authz_p,
+ svn_stream_t *stream,
+ svn_stream_t *groups_stream,
+ svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- apr_pool_t *scratch_pool = svn_pool_create(pool);
- svn_authz_t *authz = apr_pcalloc(pool, sizeof(*authz));
- authz->pool = pool;
+ svn_authz_t *authz = apr_pcalloc(result_pool, sizeof(*authz));
+ authz->pool = result_pool;
/* Parse the configuration and construct the full authz model from it. */
- SVN_ERR(svn_authz__parse(&authz->full, stream, groups_stream, pool,
- scratch_pool));
-
- svn_pool_destroy(scratch_pool);
+ SVN_ERR(svn_authz__parse(&authz->full, stream, groups_stream,
+ warning_func, warning_baton,
+ result_pool, scratch_pool));
*authz_p = authz;
return SVN_NO_ERROR;
Modified: subversion/trunk/subversion/libsvn_repos/authz.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/authz.h?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/authz.h (original)
+++ subversion/trunk/subversion/libsvn_repos/authz.h Tue Jan 22 14:34:55 2019
@@ -312,6 +312,8 @@ svn_error_t *
svn_authz__parse(authz_full_t **authz,
svn_stream_t *rules,
svn_stream_t *groups,
+ svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
Modified: subversion/trunk/subversion/libsvn_repos/authz_parse.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/authz_parse.c?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/authz_parse.c (original)
+++ subversion/trunk/subversion/libsvn_repos/authz_parse.c Tue Jan 22 14:34:55 2019
@@ -127,6 +127,10 @@ typedef struct ctor_baton_t
svn_membuf_t rule_path_buffer;
svn_stringbuf_t *rule_string_buffer;
+ /* The warning callback and its baton. */
+ svn_repos_authz_warning_func_t warning_func;
+ void *warning_baton;
+
/* The parser's scratch pool. This may not be the same pool as
passed to the constructor callbacks, that is supposed to be an
iteration pool maintained by the generic parser.
@@ -203,7 +207,9 @@ insert_default_acl(ctor_baton_t *cb)
/* Initialize a constuctor baton. */
static ctor_baton_t *
-create_ctor_baton(apr_pool_t *result_pool,
+create_ctor_baton(svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
apr_pool_t *const parser_pool = svn_pool_create(scratch_pool);
@@ -234,6 +240,9 @@ create_ctor_baton(apr_pool_t *result_poo
svn_membuf__create(&cb->rule_path_buffer, 0, parser_pool);
cb->rule_string_buffer = svn_stringbuf_create_empty(parser_pool);
+ cb->warning_func = warning_func;
+ cb->warning_baton = warning_baton;
+
cb->parser_pool = parser_pool;
insert_default_acl(cb);
@@ -242,6 +251,25 @@ create_ctor_baton(apr_pool_t *result_poo
}
+/* Emit a warning. Clears ERROR */
+static void
+emit_parser_warning(const ctor_baton_t *cb,
+ svn_error_t *error,
+ apr_pool_t *scratch_pool)
+{
+ if (cb->warning_func)
+ cb->warning_func(cb->warning_baton, error, scratch_pool);
+ svn_error_clear(error);
+}
+
+/* Avoid creating an error struct if there is no warning function. */
+#define SVN_AUTHZ_PARSE_WARN(cb, err, pool) \
+ do { \
+ if ((cb) && (cb)->warning_func) \
+ emit_parser_warning((cb), (err), (pool)); \
+ } while(0)
+
+
/* Create and store per-user global rights.
The USER string must be interned or statically initialized. */
static void
@@ -1186,8 +1214,14 @@ array_insert_ace(void *baton,
}
else if (0 == apr_hash_count(ace->members))
{
- /* TODO: Somehow emit a warning about the use of an empty group. */
/* An ACE for an empty group has no effect, so ignore it. */
+ SVN_AUTHZ_PARSE_WARN(
+ iab->cb,
+ svn_error_createf(
+ SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+ _("Ignoring access entry for empty group '%s'"),
+ ace->name),
+ scratch_pool);
return SVN_NO_ERROR;
}
}
@@ -1335,10 +1369,13 @@ svn_error_t *
svn_authz__parse(authz_full_t **authz,
svn_stream_t *rules,
svn_stream_t *groups,
+ svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- ctor_baton_t *const cb = create_ctor_baton(result_pool, scratch_pool);
+ ctor_baton_t *const cb = create_ctor_baton(warning_func, warning_baton,
+ result_pool, scratch_pool);
/*
* Pass 1: Parse the authz file.
Modified: subversion/trunk/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/deprecated.c?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_repos/deprecated.c Tue Jan 22 14:34:55 2019
@@ -1273,6 +1273,21 @@ svn_repos_fs_begin_txn_for_update(svn_fs
/*** From authz.c ***/
svn_error_t *
+svn_repos_authz_read3(svn_authz_t **authz_p,
+ const char *path,
+ const char *groups_path,
+ svn_boolean_t must_exist,
+ svn_repos_t *repos_hint,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(svn_repos_authz_read4(authz_p, path, groups_path,
+ must_exist, repos_hint,
+ NULL, NULL, result_pool,
+ scratch_pool));
+}
+
+svn_error_t *
svn_repos_authz_read2(svn_authz_t **authz_p,
const char *path,
const char *groups_path,
@@ -1300,3 +1315,17 @@ svn_repos_authz_read(svn_authz_t **authz
return svn_error_trace(svn_repos_authz_read2(authz_p, file, NULL,
must_exist, pool));
}
+
+svn_error_t *
+svn_repos_authz_parse(svn_authz_t **authz_p,
+ svn_stream_t *stream,
+ svn_stream_t *groups_stream,
+ apr_pool_t *pool)
+{
+ apr_pool_t *scratch_pool = svn_pool_create(pool);
+ svn_error_t *err = svn_repos_authz_parse2(authz_p, stream, groups_stream,
+ NULL, NULL, pool, scratch_pool);
+ svn_pool_destroy(scratch_pool);
+
+ return svn_error_trace(err);
+}
Modified: subversion/trunk/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_authz_svn/mod_authz_svn.c?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/trunk/subversion/mod_authz_svn/mod_authz_svn.c Tue Jan 22 14:34:55 2019
@@ -327,16 +327,17 @@ log_access_verdict(LOG_ARGS_SIGNATURE,
}
}
-/* Log a message indiciating the ERR encountered during the request R.
+/* Log a message at LOG_LEVEL indiciating the ERR encountered during
+ * the request R.
* LOG_ARGS_SIGNATURE expands as in log_access_verdict() above.
* PREFIX is inserted at the start of the message. The rest of the
* message is generated by combining the message for each error in the
* chain of ERR, excluding for trace errors. ERR will be cleared
* when finished. */
static void
-log_svn_error(LOG_ARGS_SIGNATURE,
- request_rec *r, const char *prefix,
- svn_error_t *err, apr_pool_t *scratch_pool)
+log_svn_message(LOG_ARGS_SIGNATURE, int log_level,
+ request_rec *r, const char *prefix,
+ svn_error_t *err, apr_pool_t *scratch_pool)
{
svn_error_t *err_pos = svn_error_purge_tracing(err);
svn_stringbuf_t *buff = svn_stringbuf_create(prefix, scratch_pool);
@@ -360,7 +361,7 @@ log_svn_error(LOG_ARGS_SIGNATURE,
err_pos = err_pos->child;
}
- ap_log_rerror(LOG_ARGS_CASCADE, APLOG_ERR,
+ ap_log_rerror(LOG_ARGS_CASCADE, log_level,
/* If it is an error code that APR can make sense of, then
show it, otherwise, pass zero to avoid putting "APR does
not understand this error code" in the error log. */
@@ -372,6 +373,40 @@ log_svn_error(LOG_ARGS_SIGNATURE,
svn_error_clear(err);
}
+/* Log the error error ERR encountered during the request R.
+ * LOG_ARGS_SIGNATURE expands as in log_access_verdict() above.
+ * PREFIX is inserted at the start of the message. The rest of the
+ * message is generated by combining the message for each error in the
+ * chain of ERR, excluding for trace errors. ERR will be cleared
+ * when finished. */
+static APR_INLINE void
+log_svn_error(LOG_ARGS_SIGNATURE,
+ request_rec *r, const char *prefix,
+ svn_error_t *err, apr_pool_t *scratch_pool)
+{
+ log_svn_message(LOG_ARGS_CASCADE, APLOG_ERR,
+ r, prefix, err, scratch_pool);
+}
+
+/* Baton for log_authz_warning. */
+typedef struct authz_warning_baton_t
+{
+ request_rec *r;
+ const char *prefix;
+} authz_warning_baton_t;
+
+/* Handle an authz parser warning. ERR will *not* be cleared.*/
+static APR_INLINE void
+log_authz_warning(void *baton,
+ const svn_error_t *err,
+ apr_pool_t *scratch_pool)
+{
+ const authz_warning_baton_t *const warning_baton = baton;
+ log_svn_message(APLOG_MARK, APLOG_WARNING,
+ warning_baton->r, warning_baton->prefix,
+ svn_error_dup(err), scratch_pool);
+}
+
/* Resolve *PATH into an absolute canonical URL iff *PATH is a repos-relative
* URL. If *REPOS_URL is NULL convert REPOS_PATH into a file URL stored
* in *REPOS_URL, if *REPOS_URL is not null REPOS_PATH is ignored. The
@@ -472,8 +507,13 @@ get_access_conf(request_rec *r, authz_sv
access_conf = user_data;
if (access_conf == NULL)
{
- svn_err = svn_repos_authz_read3(&access_conf, access_file,
+ authz_warning_baton_t warning_baton;
+ warning_baton.r = r;
+ warning_baton.prefix = "mod_authz_svn: warning:";
+
+ svn_err = svn_repos_authz_read4(&access_conf, access_file,
groups_file, TRUE, NULL,
+ log_authz_warning, &warning_baton,
r->connection->pool,
scratch_pool);
Modified: subversion/trunk/subversion/svnserve/logger.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/logger.c?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/logger.c (original)
+++ subversion/trunk/subversion/svnserve/logger.c Tue Jan 22 14:34:55 2019
@@ -88,19 +88,21 @@ logger__create(logger_t **logger,
return SVN_NO_ERROR;
}
-void
-logger__log_error(logger_t *logger,
- svn_error_t *err,
- repository_t *repository,
- client_info_t *client_info)
+static void
+log_message(logger_t *logger,
+ const svn_error_t *err,
+ const char *prefix,
+ repository_t *repository,
+ client_info_t *client_info)
{
if (logger && err)
{
const char *timestr, *continuation;
const char *user, *repos, *remote_host;
- char errbuf[256];
+
/* 8192 from MAX_STRING_LEN in from httpd-2.2.4/include/httpd.h */
- char errstr[8192];
+ const apr_size_t errstr_size = 8192;
+ char *errstr = apr_palloc(logger->pool, errstr_size);
svn_error_clear(svn_mutex__lock(logger->mutex));
@@ -118,21 +120,22 @@ logger__log_error(logger_t *logger,
continuation = "";
while (err)
{
+ char errbuf[256];
const char *message = svn_err_best_message(err, errbuf, sizeof(errbuf));
/* based on httpd-2.2.4/server/log.c:log_error_core */
- apr_size_t len = apr_snprintf(errstr, sizeof(errstr),
+ apr_size_t len = apr_snprintf(errstr, errstr_size,
"%" APR_PID_T_FMT
- " %s %s %s %s ERR%s %s %ld %d ",
+ " %s %s %s %s %s%s %s %ld %d ",
getpid(), timestr, remote_host, user,
- repos, continuation,
+ repos, prefix, continuation,
err->file ? err->file : "-", err->line,
err->apr_err);
len += escape_errorlog_item(errstr + len, message,
- sizeof(errstr) - len);
+ errstr_size - len);
/* Truncate for the terminator (as apr_snprintf does) */
- if (len > sizeof(errstr) - sizeof(APR_EOL_STR)) {
- len = sizeof(errstr) - sizeof(APR_EOL_STR);
+ if (len > errstr_size - sizeof(APR_EOL_STR)) {
+ len = errstr_size - sizeof(APR_EOL_STR);
}
memcpy(errstr + len, APR_EOL_STR, sizeof(APR_EOL_STR));
@@ -150,6 +153,24 @@ logger__log_error(logger_t *logger,
}
}
+void
+logger__log_error(logger_t *logger,
+ const svn_error_t *err,
+ repository_t *repository,
+ client_info_t *client_info)
+{
+ log_message(logger, err, "ERR", repository, client_info);
+}
+
+void
+logger__log_warning(logger_t *logger,
+ const svn_error_t *err,
+ repository_t *repository,
+ client_info_t *client_info)
+{
+ log_message(logger, err, "WARN", repository, client_info);
+}
+
svn_error_t *
logger__write(logger_t *logger,
const char *errstr,
Modified: subversion/trunk/subversion/svnserve/logger.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/logger.h?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/logger.h (original)
+++ subversion/trunk/subversion/svnserve/logger.h Tue Jan 22 14:34:55 2019
@@ -64,14 +64,21 @@ logger__write(logger_t *logger,
/* Write a description of ERR with additional information from REPOSITORY
* and CLIENT_INFO to the log file managed by LOGGER. REPOSITORY as well
* as CLIENT_INFO may be NULL. If either ERR or LOGGER are NULL, this
- * becomes a no-op.
+ * becomes a no-op. Does not clear ERR.
*/
void
logger__log_error(logger_t *logger,
- svn_error_t *err,
+ const svn_error_t *err,
repository_t *repository,
client_info_t *client_info);
+/* Like logger__log_error() but for warnings. */
+void
+logger__log_warning(logger_t *logger,
+ const svn_error_t *err,
+ repository_t *repository,
+ client_info_t *client_info);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/trunk/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/serve.c?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/serve.c (original)
+++ subversion/trunk/subversion/svnserve/serve.c Tue Jan 22 14:34:55 2019
@@ -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 *
@@ -294,7 +301,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 +323,18 @@ load_authz_config(repository_t *reposito
/* 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);
@@ -3793,6 +3804,8 @@ 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)
{
@@ -3870,7 +3883,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,
@@ -4092,6 +4106,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
*/
@@ -4214,10 +4238,14 @@ construct_server_baton(server_baton_t **
}
}
+ /* (*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)
Modified: subversion/trunk/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/authz_tests.py?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/authz_tests.py Tue Jan 22 14:34:55 2019
@@ -1694,7 +1694,7 @@ def inverted_group_membership(sbox):
@Skip(svntest.main.is_ra_type_file)
def group_member_empty_string(sbox):
- "group definition ignores with empty member"
+ "group definition ignores empty member"
sbox.build(create_wc = False)
@@ -1710,6 +1710,27 @@ def group_member_empty_string(sbox):
'--username', svntest.main.wc_author,
sbox.repo_url)
+@Issue(4802)
+@Skip(svntest.main.is_ra_type_file)
+def empty_group(sbox):
+ "empty group is ignored"
+
+ sbox.build(create_wc = False)
+
+ write_restrictive_svnserve_conf(sbox.repo_dir)
+ write_authz_file(sbox,
+ {"/" : ("$anonymous =\n"
+ "@empty = rw\n"
+ "@readonly = r\n")},
+ {"groups": ("empty = \n"
+ "readonly = %s\n" % svntest.main.wc_author)})
+
+ expected_output = svntest.verify.UnorderedOutput(['A/\n', 'iota\n'])
+ svntest.actions.run_and_verify_svn(expected_output, [],
+ 'list',
+ '--username', svntest.main.wc_author,
+ sbox.repo_url)
+
########################################################################
# Run the tests
@@ -1749,6 +1770,7 @@ test_list = [ None,
remove_access_after_commit,
inverted_group_membership,
group_member_empty_string,
+ empty_group,
]
serial_only = True
Modified: subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py Tue Jan 22 14:34:55 2019
@@ -965,7 +965,7 @@ def svnauthz_inverted_selector_test(sbox
os.remove(authz_path)
-@Issue(4802)
+@Issues(4802, 4803)
def svnauthz_empty_group_test(sbox):
"test empty group definition"
@@ -984,12 +984,15 @@ def svnauthz_empty_group_test(sbox):
(authz_fd, authz_path) = tempfile.mkstemp()
svntest.main.file_write(authz_path, authz_content)
+ expected_stderr = svntest.verify.RegexOutput(
+ r".*warning: W220003:.*", match_all=False)
+
svntest.actions.run_and_verify_svnauthz(
- [], None, 0, False, 'validate', authz_path)
+ [], expected_stderr, 0, False, 'validate', authz_path)
svntest.actions.run_and_verify_svnauthz(
- 'r', None, 0, False, 'accessof',
- '--repository', 'A', '--username', 'user', authz_path)
+ 'r', expected_stderr, 0, False, 'accessof',
+ '--repository', 'A', '--username', 'user', authz_path)
########################################################################
Modified: subversion/trunk/subversion/tests/libsvn_repos/authz-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_repos/authz-test.c?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_repos/authz-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_repos/authz-test.c Tue Jan 22 14:34:55 2019
@@ -212,7 +212,7 @@ test_authz_parse(const svn_test_opts_t *
APR_READ, APR_OS_DEFAULT,
pool));
groups = svn_stream_from_aprfile2(groups_file, FALSE, pool);
- SVN_ERR(svn_authz__parse(&authz, rules, groups, pool, pool));
+ SVN_ERR(svn_authz__parse(&authz, rules, groups, NULL, NULL, pool, pool));
printf("Access check for ('%s', '%s')\n", check_user, check_repo);
@@ -304,7 +304,7 @@ run_global_rights_tests(const char *cont
svn_stringbuf_t *buffer = svn_stringbuf_create(contents, pool);
svn_stream_t *stream = svn_stream_from_stringbuf(buffer, pool);
- SVN_ERR(svn_repos_authz_parse(&authz, stream, NULL, pool));
+ SVN_ERR(svn_repos_authz_parse2(&authz, stream, NULL, NULL, NULL, pool, pool));
for (; test_cases->repos; ++test_cases)
{
@@ -463,7 +463,7 @@ issue_4741_groups(apr_pool_t *pool)
svn_authz_t *authz;
svn_boolean_t access_granted;
- SVN_ERR(svn_repos_authz_parse(&authz, stream, NULL, pool));
+ SVN_ERR(svn_repos_authz_parse2(&authz, stream, NULL, NULL, NULL, pool, pool));
SVN_ERR(svn_repos_authz_check_access(authz, "repo", "/", "userA",
svn_authz_write, &access_granted,
@@ -500,7 +500,7 @@ reposful_reposless_stanzas_inherit(apr_p
svn_authz_t *authz;
svn_boolean_t access_granted;
- SVN_ERR(svn_repos_authz_parse(&authz, stream, NULL, pool));
+ SVN_ERR(svn_repos_authz_parse2(&authz, stream, NULL, NULL, NULL, pool, pool));
SVN_ERR(svn_repos_authz_check_access(authz, "project1", "/foo", "user1",
svn_authz_write | svn_authz_recursive,
Modified: subversion/trunk/tools/server-side/svnauthz.c
URL: http://svn.apache.org/viewvc/subversion/trunk/tools/server-side/svnauthz.c?rev=1851823&r1=1851822&r2=1851823&view=diff
==============================================================================
--- subversion/trunk/tools/server-side/svnauthz.c (original)
+++ subversion/trunk/tools/server-side/svnauthz.c Tue Jan 22 14:34:55 2019
@@ -31,6 +31,7 @@
#include "private/svn_fspath.h"
#include "private/svn_cmdline_private.h"
+#include "svn_private_config.h"
/*** Option Processing. ***/
@@ -99,6 +100,9 @@ struct svnauthz_opt_state
/* Libtool command prefix */
#define SVNAUTHZ_LT_PREFIX "lt-"
+/* The prefix for handling errors and warnings. */
+#define SVNAUTHZ_ERR_PREFIX "svnauthz: "
+
/*** Subcommands. */
@@ -224,6 +228,18 @@ read_file_contents(svn_stream_t **conten
return SVN_NO_ERROR;
}
+/* Handles warning emitted by the authz parser. */
+static void
+handle_parser_warning(void *baton,
+ const svn_error_t *err,
+ apr_pool_t *scratch_pool)
+{
+ svn_handle_warning2(stderr, err, SVNAUTHZ_ERR_PREFIX);
+ SVN_UNUSED(baton);
+ SVN_UNUSED(scratch_pool);
+}
+
+
/* Loads the authz config into *AUTHZ from the file at AUTHZ_FILE
in repository at REPOS_PATH from the transaction TXN_NAME. If GROUPS_FILE
is set, the resulting *AUTHZ will be constructed from AUTHZ_FILE with
@@ -256,7 +272,8 @@ get_authz_from_txn(svn_authz_t **authz,
else
groups_contents = NULL;
- err = svn_repos_authz_parse(authz, authz_contents, groups_contents, pool);
+ err = svn_repos_authz_parse2(authz, authz_contents, groups_contents,
+ handle_parser_warning, NULL, pool, pool);
/* Add the filename to the error stack since the parser doesn't have it. */
if (err != SVN_NO_ERROR)
@@ -283,9 +300,11 @@ get_authz(svn_authz_t **authz, struct sv
opt_state->txn, pool);
/* Else */
- return svn_repos_authz_read3(authz, opt_state->authz_file,
+ return svn_repos_authz_read4(authz, opt_state->authz_file,
opt_state->groups_file,
- TRUE, NULL, pool, pool);
+ TRUE, NULL,
+ handle_parser_warning, NULL,
+ pool, pool);
}
static svn_error_t *
@@ -755,7 +774,7 @@ main(int argc, const char *argv[])
{
if (exit_code == 0)
exit_code = EXIT_FAILURE;
- svn_cmdline_handle_exit_error(err, NULL, "svnauthz: ");
+ svn_cmdline_handle_exit_error(err, NULL, SVNAUTHZ_ERR_PREFIX);
}
svn_pool_destroy(pool);