On Thu, Feb 07, 2013 at 03:31:54PM +0700, Victor Sudakov wrote:
> Colleagues,
>
> I use subversion-1.7.2 with cyrus-sasl-2.1.25 for Kerberos (GSSAPI)
> authentication. I have the following in svnserve.conf:
>
> [general]
> auth-access = write
> [general]
> realm = SIBPTUS.TOMSK.RU
> [sasl]
> use-sasl = true
>
> Everything works smoothly for the users (Kerberos principals) in the
> SIBPTUS.TOMSK.RU realm.
>
> How can I give repository access (authorization) to users in other
> realms which are trusted by the SIBPTUS.TOMSK.RU realm? It seems that
> "auth-access = write" is not sufficient to give them access.
>
> I would not mind if all the foreign principals were granted write
> access to the repository with their subversion ids (e.g. in logs) being
> 'user_at_FOREIGN.REALM'. Is this possible?
>
> TIA for any input.
Cross-realm auth isn't supported at present, as reported by Alec Kloss
here: http://svn.haxx.se/users/archive-2008-08/0472.shtml
And Alec also submitted a patch:
http://svn.haxx.se/dev/archive-2009-03/0650.shtml
But we never applied it due to lack of time and ability to test it:
http://svn.haxx.se/dev/archive-2010-05/0098.shtml
Would you be willing to help test this patch against 1.7 sources?
[[[
Add option cross-realm support to cyrus_auth.c. Adds three
boolean configuration entries in the [sasl] section:
enable-cross-realm: set to enable cross-realm support
remove-local-realm: set to true to remove the local realm
from a user name, false to keep the realm on a local user.
Defaults to !enable-cross-realm
remove-remote-realm: set to true to remove the realm of a remote
user. This is a potential security hazard and should not
be enabled unless you're confident all realms are trustworthy.
]]]
Index: subversion/include/svn_config.h
===================================================================
--- subversion/include/svn_config.h (revision 1439424)
+++ subversion/include/svn_config.h (working copy)
@@ -135,6 +135,9 @@ typedef struct svn_config_t svn_config_t;
#define SVN_CONFIG_OPTION_USE_SASL "use-sasl"
#define SVN_CONFIG_OPTION_MIN_SSF "min-encryption"
#define SVN_CONFIG_OPTION_MAX_SSF "max-encryption"
+#define SVN_CONFIG_OPTION_ENABLE_CROSS_REALM "enable-cross-realm"
+#define SVN_CONFIG_OPTION_REMOVE_LOCAL_REALM "remove-local-realm"
+#define SVN_CONFIG_OPTION_REMOVE_REMOTE_REALM "remove-remote-realm"
/* For repository password database */
#define SVN_CONFIG_SECTION_USERS "users"
Index: subversion/svnserve/cyrus_auth.c
===================================================================
--- subversion/svnserve/cyrus_auth.c (revision 1439424)
+++ subversion/svnserve/cyrus_auth.c (working copy)
@@ -53,7 +53,7 @@
'\0'-terminated; we just need to set *OUT_LEN correctly.
*/
static int canonicalize_username(sasl_conn_t *conn,
- void *context, /* not used */
+ server_baton_t *b, /* set by cyrus_auth_request */
const char *in, /* the username */
unsigned inlen, /* its length */
unsigned flags, /* not used */
@@ -61,11 +61,15 @@ static int canonicalize_username(sasl_conn_t *conn
char *out, /* the output buffer */
unsigned out_max, unsigned *out_len)
{
+ svn_boolean_t crossrealm_enabled;
int realm_len = strlen(user_realm);
char *pos;
*out_len = inlen;
+ svn_config_get_server_setting_bool(b->cfg, &crossrealm_enabled,
+ SVN_CONFIG_SECTION_SASL, SVN_CONFIG_OPTION_ENABLE_CROSS_REALM, FALSE);
+
/* If the username contains an '@', the part after the '@' is the realm
that the user wants to authenticate in. */
pos = memchr(in, '@', inlen);
@@ -73,7 +77,7 @@ static int canonicalize_username(sasl_conn_t *conn
{
/* The only valid realm is user_realm (i.e. the repository's realm).
If the user gave us another realm, complain. */
- if (strncmp(pos+1, user_realm, inlen-(pos-in+1)) != 0)
+ if (!crossrealm_enabled && strncmp(pos+1, user_realm, inlen-(pos-in+1)) != 0)
return SASL_BADPROT;
}
else
@@ -96,6 +100,7 @@ static int canonicalize_username(sasl_conn_t *conn
return SASL_OK;
}
+static int callbackslen = 2;
static sasl_callback_t callbacks[] =
{
{ SASL_CB_CANON_USER, canonicalize_username, NULL },
@@ -255,6 +260,7 @@ svn_error_t *cyrus_auth_request(svn_ra_svn_conn_t
sasl_security_properties_t secprops;
svn_boolean_t success, no_anonymous;
int mech_count, result = SASL_OK;
+ sasl_callback_t *my_callbacks;
SVN_ERR(svn_ra_svn__get_addresses(&localaddrport, &remoteaddrport,
conn, pool));
@@ -266,12 +272,23 @@ svn_error_t *cyrus_auth_request(svn_ra_svn_conn_t
return svn_ra_svn_flush(conn, pool);
}
+ /* Initialize my own callbacks with my context */
+ my_callbacks = apr_palloc(pool, callbackslen*sizeof(sasl_callback_t));
+ if (!my_callbacks)
+ {
+ svn_error_t *err = svn_error_wrap_apr(apr_err, _("Can't allocate memory"));
+ SVN_ERR(write_failure(conn, pool, &err));
+ return svn_ra_svn_flush(conn, pool);
+ }
+ memcpy(my_callbacks, callbacks, callbackslen*sizeof(sasl_callback_t));
+ my_callbacks[0].context = b;
+
/* Create a SASL context. SASL_SUCCESS_DATA tells SASL that the protocol
supports sending data along with the final "success" message. */
result = sasl_server_new(SVN_RA_SVN_SASL_NAME,
hostname, b->realm,
localaddrport, remoteaddrport,
- NULL, SASL_SUCCESS_DATA,
+ my_callbacks, SASL_SUCCESS_DATA,
&sasl_ctx);
if (result != SASL_OK)
{
@@ -350,6 +367,9 @@ svn_error_t *cyrus_auth_request(svn_ra_svn_conn_t
if (no_anonymous)
{
+ svn_boolean_t crossrealm_enabled;
+ svn_boolean_t remove_local_realm;
+ svn_boolean_t remove_remote_realm;
char *p;
const void *user;
@@ -359,10 +379,27 @@ svn_error_t *cyrus_auth_request(svn_ra_svn_conn_t
if (result != SASL_OK)
return fail_cmd(conn, pool, sasl_ctx);
+ svn_config_get_server_setting_bool(b->cfg, &crossrealm_enabled,
+ SVN_CONFIG_SECTION_SASL, SVN_CONFIG_OPTION_ENABLE_CROSS_REALM, FALSE);
+
+ svn_config_get_server_setting_bool(b->cfg, &remove_local_realm,
+ SVN_CONFIG_SECTION_SASL, SVN_CONFIG_OPTION_REMOVE_LOCAL_REALM, !crossrealm_enabled);
+
+ svn_config_get_server_setting_bool(b->cfg, &remove_remote_realm,
+ SVN_CONFIG_SECTION_SASL, SVN_CONFIG_OPTION_REMOVE_REMOTE_REALM, FALSE);
+
if ((p = strchr(user, '@')) != NULL)
{
- /* Drop the realm part. */
- b->user = apr_pstrndup(b->pool, user, p - (const char *)user);
+ svn_boolean_t is_local_realm = !strcmp(p+1, b->realm);
+ svn_boolean_t remove_realm =
+ remove_local_realm && is_local_realm ||
+ remove_remote_realm && !is_local_realm;
+
+ if (remove_realm)
+ /* Drop the realm part. */
+ b->user = apr_pstrndup(b->pool, user, p - (char *)user);
+ else
+ b->user = apr_pstrdup(b->pool, user);
}
else
{
Received on 2013-02-07 14:38:40 CET