You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Kyle George <kg...@tcpsoft.com> on 2007/04/20 01:47:31 UTC
[contrib] mod_authrewrite.c
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 <kg...@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
Re: [contrib] mod_authrewrite.c
Posted by Kyle George <kg...@tcpsoft.com>.
On Fri, 20 Apr 2007, C. Michael Pilato wrote:
> ...especially since said script has already been written. (See
> contrib/server-side/svn-tweak-author.py.)
Yeah, I guess you did this relatively recently (Jan 29, 2007). However,
svn-tweak-author.py won't catch the case of mapping/rewriting usernames
before it hits mod_authz_svn and/or mod_dav_svn, which is the primary
purpose for mod_authrewrite (see the comments in the source). If you want
to change svn:author historically and change your authz conf file, then
your script does the trick. mod_authrewrite lets you rewrite usernames
without having to change svn:author historically, change your authz conf
file, or install a commit hook. It can also normalize usernames to all
lower or upper case before it hits the authz_svn or dav layers.
Regards,
--
Kyle George
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: [contrib] mod_authrewrite.c
Posted by "C. Michael Pilato" <cm...@collab.net>.
Kyle George wrote:
[...]
> 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).
...especially since said script has already been written. (See
contrib/server-side/svn-tweak-author.py.)
--
C. Michael Pilato <cm...@collab.net>
CollabNet <> www.collab.net <> Distributed Development On Demand