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

[contrib] mod_authrewrite.c

From: Kyle George <kgeorge_at_tcpsoft.com>
Date: 2007-04-20 03:47:31 CEST

Dev,

The subversion repository I maintain had to change authentication schemes
and usernames due to an acquisition. This would mean that future
revisions would show up with the new usernames. This would break some
management tools, stats, and general consistency. Instead of going back
and resetting the svn:author property to the new usernames historically, I
wrote this apache module that sits in between the authn provider and
mod_authz_svn/mod_dav_svn and maps the new usernames to the old usernames
for me. It was written primarily for fun (it would have been much easier
to write a script to reset svn:author).

I'd like to contribute it to anyone else who might find it useful. Read
the comments below for details.

I'll admit not being an apache module expert, so patches are welcome from
anyone who is.

Regards,

-- 
Kyle George
mod_authrewrite.c:
/*
  * Copyright (c) 2007 Kyle George <kgeorge@tcpsoft.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
  *
  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
/*
  * mod_authrewrite.c: An apache2 module that sits between mod_authz_svn,
  * other auth(n|z) modules, and the subversion dav backend (mod_dav_svn).
  * It rewrites the auth'ed usernames for case and translates them using
  * simple map lookup.
  *
  * It's useful if you change authentication schemes where users must use
  * new usernames and you want the svn:author prop to stay consistent, or
  * if your users can't type their names in a single case.  It will also
  * keep you from having to change your mod_authz_svn conf file.
  *
  * Example: You go from using basic authentication using first initial +
  * last name to integrating with an LDAP directory where users will now
  * authenticate with their full email address.  The email address is what
  * will now show up to mod_dav_svn.  If you want to keep your repository
  * svn:author consistent and/or keep from having to change your
  * mod_authz_svn configuration, use this module to map the email
  * addresses to the old usernames.
  *
  * Use this module with:
  *
  *   AuthRewriteCase "lower"|"upper"
  *   AuthRewriteMapEntry <from> <to>
  *
  * TODO: Eventually, it'd be cool if it supported mod_rewrite-like
  * options like:
  *
  *   AuthRewriteEngine "on"|"off"
  *   AuthRewriteMap <mapname> <maptype>:<source>
  *   AuthRewriteCond <teststring> <condpattern> <flags>
  *   AuthRewriteLogLevel <level>
  *   AuthRewriteOptions <options>
  *   AuthRewriteRule <pattern> <substitution> <flags>
  *
  *   ... or at least an external map file, but it doesn't do that now.
  *
  * To compile and install:
  *
  *   1) # /path/to/apache2/bin/apxs -c mod_authrewrite.c
  *   2) # cp .libs/mod_authrewrite.so /path/to/apache2/modules
  *   3) Put "LoadModule authrewrite_module modules/mod_authrewrite.so"
  *      in your httpd.conf (or appropriate).
  *   4) Configure directives
  *   5) Restart apache2
  */
#include "apr.h"
#include "apr_lib.h"
#include "apr_pools.h"
#include "apr_general.h"
#include "apr_strings.h"
#include "ap_config.h"
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_request.h"
#include "http_log.h"
/*
  * Decls/defs
  */
module AP_MODULE_DECLARE_DATA authrewrite_module;
typedef struct {
#define REWRITE_CASE_OFF   0
#define REWRITE_CASE_LOWER 1
#define REWRITE_CASE_UPPER 2
   int rewrite_case;
   apr_table_t *rewrite_memmap;
} authrewrite_config;
/*
  * Utils
  */
/*
  * Convert s to lower case in place
  */
static char *strlwr(char *s)
{
   char *r = s;
   while (s && *s) {
     *s++ = apr_tolower(*s);
   }
   return (r);
}
/*
  * Convert s to upper case in place
  */
static char *strupr(char *s)
{
   char *r = s;
   while (s && *s) {
     *s++ = apr_toupper(*s);
   }
   return (r);
}
/*
  * Per-directory config
  */
/*
  * Create per-directory config
  */
static void *authrewrite_config_create(apr_pool_t *p, char *dummy)
{
   authrewrite_config *new = NULL;
   new = apr_pcalloc(p, sizeof(authrewrite_config));
   new->rewrite_case = REWRITE_CASE_OFF;
   new->rewrite_memmap = apr_table_make(p, 1);
   return ((void *)new);
}
/*
  * Hooks
  */
/*
  * Fixup username
  */
static int authrewrite_fixup(request_rec *r)
{
   const char *s = NULL;
   const char *u = NULL;
   authrewrite_config *c = NULL;
   c = (authrewrite_config *)
     ap_get_module_config(
       r->per_dir_config,
       &authrewrite_module
     );
   if (c == NULL) {
     return (DECLINED);
   }
   /* dup original username */
   u = apr_pstrdup(r->pool, r->user);
   /* rewrite case */
   switch (c->rewrite_case) {
   case REWRITE_CASE_LOWER: r->user = strlwr(r->user); break;
   case REWRITE_CASE_UPPER: r->user = strupr(r->user); break;
   }
   /* rewrite map */
   if ((s = apr_table_get(c->rewrite_memmap, r->user)) != NULL) {
     r->user = (char *)apr_pstrdup(r->pool, s);
   }
   /* preserve original username */
   apr_pool_userdata_set(u, "mod_authrewrite", NULL, r->pool);
   return (DECLINED);
}
/*
  * Reset username
  */
static int authrewrite_reset(request_rec *r)
{
   void *data = NULL;
   if (apr_pool_userdata_get(&data, "mod_authrewrite", r->pool) !=
         APR_SUCCESS) {
     return (DECLINED);
   }
   if (data) {
     r->user = (char *)data;
   }
   return (DECLINED);
}
/*
  * Register callbacks
  */
static void authrewrite_register_hooks(apr_pool_t *p)
{
   static const char * const pre[] = { "mod_ssl.c", NULL };
   static const char * const post[] = { "mod_authz_svn.c", NULL };
   ap_hook_access_checker(authrewrite_fixup, NULL, post, APR_HOOK_LAST);
   ap_hook_access_checker(authrewrite_reset, post, NULL, APR_HOOK_LAST);
   ap_hook_check_user_id(authrewrite_fixup, pre, post, APR_HOOK_FIRST);
   ap_hook_check_user_id(authrewrite_reset, post, NULL, APR_HOOK_FIRST);
   ap_hook_auth_checker(authrewrite_fixup, NULL, post, APR_HOOK_FIRST);
   ap_hook_auth_checker(authrewrite_reset, post, NULL, APR_HOOK_FIRST);
   ap_hook_fixups(authrewrite_fixup, NULL, NULL, APR_HOOK_FIRST);
}
/*
  * Commands
  */
/*
  * Handle AuthRewriteCase
  */
static const char *authrewrite_command_case(cmd_parms *cmd, void *d,
   const char *arg)
{
   authrewrite_config *c = d;
   if (strcasecmp(arg, "lower") == 0) {
     c->rewrite_case = REWRITE_CASE_LOWER;
   } else
   if (strcasecmp(arg, "upper") == 0) {
     c->rewrite_case = REWRITE_CASE_UPPER;
   } else {
     c->rewrite_case = REWRITE_CASE_OFF;
   }
   return (NULL);
}
/*
  * Handle AuthRewriteMapEntry
  */
static const char *authrewrite_command_mapentry(cmd_parms *cmd, void *d,
   const char *arg0, const char *arg1)
{
   char *key = NULL;
   char *value = NULL;
   authrewrite_config *c = d;
   key = apr_pstrdup(cmd->pool, arg0);
   value = apr_pstrdup(cmd->pool, arg1);
   apr_table_setn(c->rewrite_memmap, key, value);
   return (NULL);
}
/*
  * Command table
  */
static const command_rec authrewrite_commands[] =
{
   AP_INIT_TAKE1("AuthRewriteCase", authrewrite_command_case,
     NULL, OR_OPTIONS, "Lower or upper"),
   AP_INIT_TAKE2("AuthRewriteMapEntry", authrewrite_command_mapentry,
     NULL, OR_OPTIONS, "Add a from --> to entry to the map"),
   { NULL }
};
/*
  * Module definition
  */
module AP_MODULE_DECLARE_DATA authrewrite_module =
{
   STANDARD20_MODULE_STUFF,
   authrewrite_config_create,
   NULL,
   NULL,
   NULL,
   authrewrite_commands,
   authrewrite_register_hooks
};
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Apr 20 03:47:41 2007

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.