Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/svnserve/serve.c view on Meta::CPAN
{
authz_baton_t *sb = baton;
return authz_check_access(allowed, path, svn_authz_read,
sb->server, sb->conn, pool);
}
/* If authz is enabled in the specified BATON, return a read authorization
function. Otherwise, return NULL. */
static svn_repos_authz_func_t authz_check_access_cb_func(server_baton_t *baton)
{
if (baton->authzdb)
return authz_check_access_cb;
return NULL;
}
/* Set *ALLOWED to TRUE if the REQUIRED access to PATH is granted,
* according to the state in BATON. Use POOL for temporary
* allocations only. ROOT is not used. Implements the
* svn_repos_authz_callback_t interface.
*/
static svn_error_t *authz_commit_cb(svn_repos_authz_access_t required,
svn_boolean_t *allowed,
svn_fs_root_t *root,
const char *path,
void *baton,
apr_pool_t *pool)
{
authz_baton_t *sb = baton;
return authz_check_access(allowed, path, required,
sb->server, sb->conn, pool);
}
enum access_type get_access(server_baton_t *b, enum authn_type auth)
{
const char *var = (auth == AUTHENTICATED) ? SVN_CONFIG_OPTION_AUTH_ACCESS :
SVN_CONFIG_OPTION_ANON_ACCESS;
const char *val, *def = (auth == AUTHENTICATED) ? "write" : "read";
enum access_type result;
svn_config_get(b->cfg, &val, SVN_CONFIG_SECTION_GENERAL, var, def);
result = (strcmp(val, "write") == 0 ? WRITE_ACCESS :
strcmp(val, "read") == 0 ? READ_ACCESS : NO_ACCESS);
return (result == WRITE_ACCESS && b->read_only) ? READ_ACCESS : result;
}
static enum access_type current_access(server_baton_t *b)
{
return get_access(b, (b->user) ? AUTHENTICATED : UNAUTHENTICATED);
}
/* Send authentication mechs for ACCESS_TYPE to the client. If NEEDS_USERNAME
is true, don't send anonymous mech even if that would give the desired
access. */
static svn_error_t *send_mechs(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
server_baton_t *b, enum access_type required,
svn_boolean_t needs_username)
{
if (!needs_username && get_access(b, UNAUTHENTICATED) >= required)
SVN_ERR(svn_ra_svn__write_word(conn, pool, "ANONYMOUS"));
if (b->tunnel_user && get_access(b, AUTHENTICATED) >= required)
SVN_ERR(svn_ra_svn__write_word(conn, pool, "EXTERNAL"));
if (b->pwdb && get_access(b, AUTHENTICATED) >= required)
SVN_ERR(svn_ra_svn__write_word(conn, pool, "CRAM-MD5"));
return SVN_NO_ERROR;
}
/* Context for cleanup handler. */
struct cleanup_fs_access_baton
{
svn_fs_t *fs;
apr_pool_t *pool;
};
/* Pool cleanup handler. Make sure fs's access_t points to NULL when
the command pool is destroyed. */
static apr_status_t cleanup_fs_access(void *data)
{
svn_error_t *serr;
struct cleanup_fs_access_baton *baton = data;
serr = svn_fs_set_access(baton->fs, NULL);
if (serr)
{
apr_status_t apr_err = serr->apr_err;
svn_error_clear(serr);
return apr_err;
}
return APR_SUCCESS;
}
/* Create an svn_fs_access_t in POOL for USER and associate it with
B's filesystem. Also, register a cleanup handler with POOL which
de-associates the svn_fs_access_t from B's filesystem. */
static svn_error_t *
create_fs_access(server_baton_t *b, apr_pool_t *pool)
{
svn_fs_access_t *fs_access;
struct cleanup_fs_access_baton *cleanup_baton;
if (!b->user)
return SVN_NO_ERROR;
SVN_ERR(svn_fs_create_access(&fs_access, b->user, pool));
SVN_ERR(svn_fs_set_access(b->fs, fs_access));
cleanup_baton = apr_pcalloc(pool, sizeof(*cleanup_baton));
cleanup_baton->pool = pool;
cleanup_baton->fs = b->fs;
apr_pool_cleanup_register(pool, cleanup_baton, cleanup_fs_access,
apr_pool_cleanup_null);
return SVN_NO_ERROR;
}
/* Authenticate, once the client has chosen a mechanism and possibly
* sent an initial mechanism token. On success, set *success to true
* and b->user to the authenticated username (or NULL for anonymous).
* On authentication failure, report failure to the client and set
* *success to FALSE. On communications failure, return an error.
* If NEEDS_USERNAME is TRUE, don't allow anonymous authentication. */
static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
const char *mech, const char *mecharg,
server_baton_t *b, enum access_type required,
svn_boolean_t needs_username,
svn_boolean_t *success)
{
const char *user;
*success = FALSE;
if (get_access(b, AUTHENTICATED) >= required
&& b->tunnel_user && strcmp(mech, "EXTERNAL") == 0)
{
if (*mecharg && strcmp(mecharg, b->tunnel_user) != 0)
return svn_ra_svn__write_tuple(conn, pool, "w(c)", "failure",
"Requested username does not match");
b->user = b->tunnel_user;
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w()", "success"));
*success = TRUE;
return SVN_NO_ERROR;
}
if (get_access(b, UNAUTHENTICATED) >= required
&& strcmp(mech, "ANONYMOUS") == 0 && ! needs_username)
{
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w()", "success"));
*success = TRUE;
return SVN_NO_ERROR;
}
if (get_access(b, AUTHENTICATED) >= required
&& b->pwdb && strcmp(mech, "CRAM-MD5") == 0)
{
SVN_ERR(svn_ra_svn_cram_server(conn, pool, b->pwdb, &user, success));
b->user = apr_pstrdup(b->pool, user);
return SVN_NO_ERROR;
}
return svn_ra_svn__write_tuple(conn, pool, "w(c)", "failure",
"Must authenticate with listed mechanism");
}
/* Perform an authentication request using the built-in SASL implementation. */
static svn_error_t *
internal_auth_request(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
server_baton_t *b, enum access_type required,
svn_boolean_t needs_username)
{
svn_boolean_t success;
const char *mech, *mecharg;
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "success"));
SVN_ERR(send_mechs(conn, pool, b, required, needs_username));
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)c)", b->realm));
do
{
SVN_ERR(svn_ra_svn__read_tuple(conn, pool, "w(?c)", &mech, &mecharg));
if (!*mech)
break;
SVN_ERR(auth(conn, pool, mech, mecharg, b, required, needs_username,
&success));
}
while (!success);
return SVN_NO_ERROR;
}
/* Perform an authentication request in order to get an access level of
* REQUIRED or higher. Since the client may escape the authentication
* exchange, the caller should check current_access(b) to see if
* authentication succeeded. */
static svn_error_t *auth_request(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
server_baton_t *b, enum access_type required,
svn_boolean_t needs_username)
{
#ifdef SVN_HAVE_SASL
if (b->use_sasl)
return cyrus_auth_request(conn, pool, b, required, needs_username);
#endif
return internal_auth_request(conn, pool, b, required, needs_username);
}
/* Send a trivial auth notification on CONN which lists no mechanisms,
* indicating that authentication is unnecessary. Usually called in
* response to invocation of a svnserve command.
*/
static svn_error_t *trivial_auth_request(svn_ra_svn_conn_t *conn,
apr_pool_t *pool, server_baton_t *b)
{
return svn_ra_svn__write_cmd_response(conn, pool, "()c", "");
}
( run in 0.376 second using v1.01-cache-2.11-cpan-71847e10f99 )