[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Kerberos foreign principals

From: Stefan Sperling <stsp_at_elego.de>
Date: Thu, 7 Feb 2013 14:37:39 +0100

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

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.