Hi,
This is a new version of mod_authz_svn which allowed compile either with
ldap or not ldap in apr-util. if apr-util has ldap then mod_authz
compile with ldap option, if not mod_authz compile without ldap option.
===================================================================
--- mod_authz_svn.c (revision 15)
+++ mod_authz_svn.c (revision 42)
@@ -16,9 +16,12 @@
* history and logs, available at http://subversion.tigris.org/.
* ====================================================================
*/
+#include<apr_ldap.h>
+#if APR_HAVE_UNISTD_H
+/* for getpid() */
+#include <unistd.h>
+#endif
#include <httpd.h>
#include <http_config.h>
#include <http_core.h>
@@ -28,13 +31,13 @@
#include <ap_config.h>
#include <apr_uri.h>
#include <mod_dav.h>
+#include "util_ldap.h"
#include "mod_dav_svn.h"
#include "svn_path.h"
#include "svn_config.h"
#include "svn_string.h"
-
extern module AP_MODULE_DECLARE_DATA authz_svn_module;
enum {
@@ -49,23 +52,63 @@
int anonymous;
const char *base_path;
const char *access_file;
-} authz_svn_config_rec;
+ /*support ldap*/
+ #if APR_HAS_THREADS
+ apr_thread_mutex_t *lock; /* Lock for this config */
+ #endif
+ #ifdef APU_HAS_LDAP
+ char *url; /* String representation of the URL */
+ char *host; /* Name of the LDAP server (or space separated list) */
+ int port; /* Port of the LDAP server */
+ char *basedn; /* Base DN to do all searches from */
+ char *attribute; /* Attribute to search for */
+ char **attributes; /* Array of all the attributes to return */
+ int scope; /* Scope of the search */
+ char *filter; /* Filter to further limit the search */
+ char *binddn; /* DN to bind to server (can be NULL) */
+ char *bindpw; /* Password to bind to server (can be NULL) */
+ deref_options deref; /* how to handle alias dereferening */
+ int have_ldap_url; /* Set if we have found an LDAP url */
+
+ apr_array_header_t *groupattr; /* List of Group attributes */
+ int group_attrib_is_dn; /* If true, the group attribute is the DN, otherwise,
+ it's the exact string passed by the HTTP client */
+ int default_group; /* For Enable Defaulf group=repos name*/
+ #endif
+} authz_svn_config_rec;
+
struct parse_authz_baton {
apr_pool_t *pool;
- svn_config_t *config;
- const char *user;
+ svn_config_t *config;
+ request_rec *r; /*Request construction*/
+ const char *user; /*User that require access*/
int allow;
int deny;
- int required_access;
- const char *repos_path;
- const char *qualified_repos_path;
+ int required_access; /*operation require by user */
+ const char *repos_path;
+ const char *qualified_repos_path; /*repos_path: repos:path*/
- int access;
+ int access; /*If true allow user access to qualified_repos_path*/
};
/*
+ * group attribute
+ */
+struct mod_authz_svn_ldap_groupattr_entry_t {
+ char *name;
+};
+
+typedef struct mod_authz_svn_ldap_request_t {
+ char *dn; /* The saved dn from a successful search */
+ char *user; /* The username provided by the client */
+} mod_authz_svn_ldap_request_t;
+
+/* maximum group elements supported */
+#define GROUPATTR_MAX_ELTS 10
+
+/*
* Configuration
*/
@@ -77,12 +120,301 @@
/* By default keep the fortress secure */
conf->authoritative = 1;
conf->anonymous = 1;
-
+ /* attribute for ldap connection */
+ #if APR_HAS_THREADS
+ apr_thread_mutex_create(&conf->lock, APR_THREAD_MUTEX_DEFAULT, p);
+ #endif
+ #ifdef APU_HAS_LDAP
+ conf->groupattr = apr_array_make(p, GROUPATTR_MAX_ELTS,
+ sizeof(struct mod_authz_svn_ldap_groupattr_entry_t));
+ conf->have_ldap_url = 0;
+ conf->url = "";
+ conf->host = NULL;
+ conf->binddn = NULL;
+ conf->bindpw = NULL;
+ conf->deref = always;
+ conf->group_attrib_is_dn = 0;
+ conf->default_group = 0;
+ #endif
return conf;
}
+
+/*
+ * This code is copied from mod_auth_ldap.c
+ * Use the ldap url parsing routines to break up the ldap url into
+ * host and port.
+ */
+#ifdef APU_HAS_LDAP
+ static const char *mod_authz_svn_ldap_parse_url(cmd_parms *cmd,
+ void *config,
+ const char *url)
+ {
+ int result;
+ apr_ldap_url_desc_t *urld;
+ authz_svn_config_rec *sec = config;
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
+ cmd->server, "[%d] authz_svn_ldap url parse: `%s'",
+ getpid(), url);
+
+ result = apr_ldap_url_parse(url, &(urld));
+ if (result != LDAP_SUCCESS) {
+ switch (result) {
+ case LDAP_URL_ERR_NOTLDAP:
+ return "LDAP URL does not begin with ldap://";
+ case LDAP_URL_ERR_NODN:
+ return "LDAP URL does not have a DN";
+ case LDAP_URL_ERR_BADSCOPE:
+ return "LDAP URL has an invalid scope";
+ case LDAP_URL_ERR_MEM:
+ return "Out of memory parsing LDAP URL";
+ default:
+ return "Could not parse LDAP URL";
+ }
+ }
+ sec->url = apr_pstrdup(cmd->pool, url);
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
+ cmd->server, "[%d] authz_svn_ldap url parse: Host: %s", getpid(), urld->lud_host);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
+ cmd->server, "[%d] authz_svn_ldap url parse: Port: %d", getpid(), urld->lud_port);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
+ cmd->server, "[%d] authz_svn_ldap url parse: DN: %s", getpid(), urld->lud_dn);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
+ cmd->server, "[%d] authz_svn_ldap url parse: DN: %s", getpid(), urld->lud_dn);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
+ cmd->server, "[%d] authz_svn_ldap url parse: scope: %s", getpid(),
+ (urld->lud_scope == LDAP_SCOPE_SUBTREE? "subtree" :
+ urld->lud_scope == LDAP_SCOPE_BASE? "base" :
+ urld->lud_scope == LDAP_SCOPE_ONELEVEL? "onelevel" : "unknown"));
+ /* Set all the values, or at least some sane defaults */
+ if (sec->host) {
+ char *p = apr_palloc(cmd->pool, strlen(sec->host) + strlen(urld->lud_host) + 2);
+ strcpy(p, urld->lud_host);
+ strcat(p, " ");
+ strcat(p, sec->host);
+ sec->host = p;
+ }
+ else {
+ sec->host = urld->lud_host? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost";
+ }
+ sec->basedn = urld->lud_dn? apr_pstrdup(cmd->pool, urld->lud_dn) : "";
+ if (urld->lud_attrs && urld->lud_attrs[0]) {
+ int i = 1;
+ while (urld->lud_attrs[i]) {
+ i++;
+ }
+ sec->attributes = apr_pcalloc(cmd->pool, sizeof(char *) * (i+1));
+ i = 0;
+ while (urld->lud_attrs[i]) {
+ sec->attributes[i] = apr_pstrdup(cmd->pool, urld->lud_attrs[i]);
+ i++;
+ }
+ sec->attribute = sec->attributes[0];
+ }
+ else {
+ sec->attribute = "uid";
+ }
+ sec->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ? LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE;
+ //filter
+ if (urld->lud_filter) {
+ if (urld->lud_filter[0] == '(') {
+ /*
+ * Get rid of the surrounding parens; later on when generating the
+ * filter, they'll be put back.
+ */
+ sec->filter = apr_pstrdup(cmd->pool, urld->lud_filter+1);
+ sec->filter[strlen(sec->filter)-1] = '\0';
+ }
+ else {
+ sec->filter = apr_pstrdup(cmd->pool, urld->lud_filter);
+ }
+ }
+ else {
+ sec->filter = "objectclass=*";
+ }
+ sec->have_ldap_url = 1;
+ apr_ldap_free_urldesc(urld);
+ return NULL;
+ }
+
+ static const char *mod_authz_svn_ldap_add_group_attribute(cmd_parms *cmd, void *config, const char *arg)
+ {
+ struct mod_authz_svn_ldap_groupattr_entry_t *new;
+ authz_svn_config_rec *sec = config;
+ if (sec->groupattr->nelts > GROUPATTR_MAX_ELTS)
+ return "Too many AuthzSVNLDAPGroupAttribute directives";
+ new = apr_array_push(sec->groupattr);
+ new->name = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+ }
+
+ static apr_status_t mod_authz_svn_ldap_cleanup_connection_close(void *param)
+ {
+ util_ldap_connection_t *ldc = param;
+ util_ldap_connection_close(ldc);
+ return APR_SUCCESS;
+ }
+
+ /*
+ * Access checking
+ */
+ static int group_ldap_contains_user_internal(request_rec *r,
+ const char *group, const char *user)
+ {
+ mod_authz_svn_ldap_request_t *req =(mod_authz_svn_ldap_request_t *)ap_get_module_config(r->request_config,&authz_svn_module);
+
+ /*get data of this module*/
+ authz_svn_config_rec *sec =(authz_svn_config_rec *)ap_get_module_config(r->per_dir_config, &authz_svn_module);
+
+ util_ldap_connection_t *ldc = NULL;
+ int result = 0;
+ const char *dn = NULL;
+ /*
+ * if the req mod_authz_svn_ldap_request_t struct hasn't been initialized
+ * causing problems when we try to use req->dn and/or req->name
+ * below. So we simply create one.
+ */
+ if (!req) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
+ "[%d] authz_svn_ldap authorise: "
+ "no req struct - skipped mod_authz_svn_ldap_check_user?",
+ getpid());
+
+ req = (mod_authz_svn_ldap_request_t *)apr_pcalloc(r->pool,
+ sizeof(mod_authz_svn_ldap_request_t));
+ ap_set_module_config(r->request_config, &authz_svn_module, req);
+ }
+
+ /*make connection to ldap server*/
+ if (sec->host) {
+ ldc = util_ldap_connection_find(r, sec->host, sec->port,
+ NULL, sec->bindpw, sec->deref,
+ 0);
+ apr_pool_cleanup_register(r->pool, ldc,
+ mod_authz_svn_ldap_cleanup_connection_close,
+ apr_pool_cleanup_null);
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
+ "[%d] authz_svn_ldap authorise: no sec->host - weird...?", getpid());
+ return DECLINED;
+ }
+
+ /*
+ * If there are no elements in the group attribute array, the default should be
+ * memberUid and uniquemember; populate the array now.
+ */
+
+ if (sec->groupattr->nelts == 0) {
+ struct mod_authz_svn_ldap_groupattr_entry_t *grp;
+ #if APR_HAS_THREADS
+ apr_thread_mutex_lock(sec->lock);
+ #endif
+ grp = apr_array_push(sec->groupattr);
+ grp->name = "memberUid";
+ grp = apr_array_push(sec->groupattr);
+ grp->name = "uniquemember";
+ #if APR_HAS_THREADS
+ apr_thread_mutex_unlock(sec->lock);
+ #endif
+ }
+ struct mod_authz_svn_ldap_groupattr_entry_t *ent = (struct mod_authz_svn_ldap_groupattr_entry_t *) sec->groupattr->elts;
+ int i;
+ /* Default group_attrib_is_dn=fault
+ * So we use just req->user
+ */
+ if (req->user == NULL || strlen(req->user) == 0) {
+ /* We weren't called in the authentication phase, so we didn't have a
+ * chance to set the user field. Do so now. */
+ req->user = r->user;
+ }
+ /*
+ * check if user in group or no
+ */
+ for (i = 0; i < sec->groupattr->nelts; i++) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
+ "[%d] authz_svn_ldap authorise: group: testing for %s: %s (%s)", getpid(),
+ ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user,group);
+
+ result = util_ldap_cache_compare(r, ldc, sec->url,group, ent[i].name,
+ sec->group_attrib_is_dn ? req->dn : req->user);
+ switch(result) {
+ case LDAP_COMPARE_TRUE: {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
+ "[%d] authz_svn_ldap authorise: group: "
+ "authorisation successful (attribute %s) [%s][%s]",
+ getpid(), ent[i].name, ldc->reason, ldap_err2string(result));
+ return OK;
+ }
+ default: {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
+ "[%d] authz_svn_ldap authorise: group \"%s\": "
+ "authorisation failed [%s][%s]",
+ getpid(),group, ldc->reason, ldap_err2string(result));
+ }
+ }
+ }//end for
+ return HTTP_UNAUTHORIZED;
+ }
+
+
+ /*
+ * check automatic access for a group default= repos name
+ */
+ static int group_default_contains_user(request_rec* r, const char *group, const char *user,int required_access,const char* value,apr_pool_t *pool)
+ {
+ struct parse_authz_baton baton = { 0 };
+ /*get data of this module*/
+ authz_svn_config_rec *sec =
+ (authz_svn_config_rec *)ap_get_module_config(r->per_dir_config, &authz_svn_module);
+ char* group_default=apr_pstrcat(pool, "cn=",group, ",",sec->binddn,NULL);
+
+ if(!sec->binddn)
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,"It must provide bind domain name for use Default group,(group=%s)",group);
+ return 0;
+ }
+ if(group_ldap_contains_user_internal(r,group_default,user))
+ return 0;
+ if (ap_strchr_c(value, 'r')) {
+ baton.allow |= AUTHZ_SVN_READ;
+ }
+ else {
+ baton.deny |= AUTHZ_SVN_READ;
+ }
+
+ if (ap_strchr_c(value, 'w')) {
+ baton.allow |= AUTHZ_SVN_WRITE;
+ }
+ else {
+ baton.deny |= AUTHZ_SVN_WRITE;
+ }
+
+ if ((baton.deny & required_access)
+ || (baton.allow & required_access))
+ return 1;
+ return (baton.deny & required_access)
+ || (baton.allow & required_access);
+ }
+#endif
+
static const command_rec authz_svn_cmds[] =
{
+ #ifdef APU_HAS_LDAP
+ AP_INIT_TAKE1("AuthzSVNLDAPURL",mod_authz_svn_ldap_parse_url, NULL, OR_AUTHCFG,
+ "URL to define LDAP connection. This should be an RFC 2255 complaint"),
+ AP_INIT_TAKE1("AuthzSVNLDAPBindDN", ap_set_string_slot,
+ (void *)APR_OFFSETOF(authz_svn_config_rec, binddn), OR_AUTHCFG,
+ "DN to use to bind to Default group LDAP. It must provide in case use Default group=repos name."),
+ AP_INIT_FLAG("AuthzSVNLDAPEnableDefaultGroup", ap_set_flag_slot,
+ (void *)APR_OFFSETOF(authz_svn_config_rec,default_group), OR_AUTHCFG,
+ "Set to off to disable check for default group=repos name."),
+ AP_INIT_ITERATE("AuthzSVNLDAPGroupAttribute", mod_authz_svn_ldap_add_group_attribute, NULL, OR_AUTHCFG,
+ "A list of attributes used to define group membership - defaults to "
+ "memberUid and uniquemember"),
+ #endif
AP_INIT_FLAG("AuthzSVNAuthoritative", ap_set_flag_slot,
(void *)APR_OFFSETOF(authz_svn_config_rec, authoritative),
OR_AUTHCFG,
@@ -101,10 +433,6 @@
};
-/*
- * Access checking
- */
-
static int group_contains_user_internal(svn_config_t *cfg,
const char *group, const char *user, apr_hash_t *checked_groups,
apr_pool_t *pool)
@@ -115,7 +443,7 @@
svn_config_get(cfg, &value, "groups", group, "");
list = svn_cstring_split(value, ",", TRUE, pool);
-
+
for (i = 0; i < list->nelts; i++) {
const char *group_user = APR_ARRAY_IDX(list, i, char *);
@@ -146,23 +474,44 @@
static int group_contains_user(svn_config_t *cfg,
const char *group, const char *user, apr_pool_t *pool)
{
- return group_contains_user_internal(cfg, group, user,
+ return group_contains_user_internal(cfg,group, user,
apr_hash_make(pool), pool);
}
+/*
+ * exemple:
+ * name:@users value:r
+ * name:@developers value:rw
+ */
static svn_boolean_t parse_authz_line(const char *name, const char *value,
void *baton)
{
struct parse_authz_baton *b = baton;
-
+ const char *ldap_group;
+ request_rec *r=b->r;
+
if (strcmp(name, "*")) {
if (!b->user) {
return TRUE;
}
-
+ /*
+ * In the access file, group ldap begin with ldap:
+ * ldap:cn=projet1,ou=group,dc=domain name
+ */
if (*name == '@') {
- if (!group_contains_user(b->config, &name[1], b->user, b->pool))
- return TRUE;
+ svn_config_get(b->config, &ldap_group, "groups", &name[1], "");
+ if(ap_strstr_c(ldap_group,"ldap:"))
+ {
+ #ifdef APU_HAS_LDAP
+ if(group_ldap_contains_user_internal(r,&ldap_group[5],b->user))
+ return TRUE;
+ #endif
+ }
+ else
+ {
+ if (!group_contains_user(b->config, &name[1], b->user, b->pool))
+ return TRUE;
+ }
}
else if (strcmp(name, b->user)) {
return TRUE;
@@ -186,14 +535,19 @@
ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, b->pool,
"%s = %s => allow = %i, deny = %i",
name, value, b->allow, b->deny);
-
return TRUE;
}
/*
* Return TRUE when ACCESS has been determined.
+ * repos name: name of reposistory(projet1)
+ * repospath: path in reposistory(/home/cong)
+ * user: username
+ * required access: user require access
+ * grant access:
*/
-static int parse_authz_lines(svn_config_t *cfg,
+
+static int parse_authz_lines(svn_config_t *cfg,request_rec *r,
const char *repos_name, const char *repos_path,
const char *user,
int required_access, int *granted_access,
@@ -205,12 +559,14 @@
baton.pool = pool;
baton.config = cfg;
baton.user = user;
-
+ baton.r=r;
+
/* First try repos specific */
qualified_repos_path = apr_pstrcat(pool, repos_name, ":", repos_path,
NULL);
svn_config_enumerate(cfg, qualified_repos_path,
parse_authz_line, &baton);
+
*granted_access = !(baton.deny & required_access)
|| (baton.allow & required_access);
@@ -222,7 +578,6 @@
parse_authz_line, &baton);
*granted_access = !(baton.deny & required_access)
|| (baton.allow & required_access);
-
return (baton.deny & required_access)
|| (baton.allow & required_access);
}
@@ -248,7 +603,7 @@
{
struct parse_authz_baton *b = baton;
int conclusive;
-
+
if (authz_path_is_ancestor (b->qualified_repos_path,
section_name) == FALSE
&& authz_path_is_ancestor (b->repos_path,
@@ -294,13 +649,17 @@
return baton.access;
}
-static int check_access(svn_config_t *cfg, const char *repos_name,
+static int check_access(svn_config_t *cfg,request_rec *r, const char *repos_name,
const char *repos_path, const char *user,
int required_access, apr_pool_t *pool)
{
const char *base_name;
const char *original_repos_path = repos_path;
int granted_access;
+
+ /*get data of this module*/
+ authz_svn_config_rec *sec =
+ (authz_svn_config_rec *)ap_get_module_config(r->per_dir_config, &authz_svn_module);
if (!repos_path) {
/* XXX: Check if the user has 'required_access' _anywhere_ in the
@@ -309,9 +668,21 @@
*/
return 1;
}
-
+ /*
+ * check automatic permission for default user group name=repos_name
+ * permission default:rw
+ */
+ #ifdef APU_HAS_LDAP
+ if(sec->default_group)
+ {
+ if(group_default_contains_user(r,repos_name,user,required_access,"rw",pool))
+ {
+ return 1;
+ }
+ }
+ #endif
base_name = repos_path;
- while (!parse_authz_lines(cfg, repos_name, repos_path,
+ while (!parse_authz_lines(cfg,r,repos_name, repos_path,
user, required_access, &granted_access,
pool)) {
if (base_name[0] == '/' && base_name[1] == '\0') {
@@ -329,7 +700,6 @@
user, required_access,
pool);
}
-
return granted_access;
}
@@ -360,7 +730,7 @@
svn_error_t *svn_err;
const char *cache_key;
void *user_data;
-
+
switch (r->method_number) {
/* All methods requiring read access to all subtrees of r->uri */
case M_COPY:
@@ -405,6 +775,7 @@
&repos_name,
&relative_path,
&repos_path);
+
if (dav_err) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"%s [%d, #%d]",
@@ -502,7 +873,7 @@
NULL, r->connection->pool);
}
- if (!check_access(access_conf,
+ if (!check_access(access_conf,r,
repos_name, repos_path,
r->user, authz_svn_type,
r->pool)) {
@@ -525,7 +896,7 @@
}
/* Check access on the first repos_path */
- if (!check_access(access_conf,
+ if (!check_access(access_conf,r,
dest_repos_name, dest_repos_path,
r->user, AUTHZ_SVN_WRITE|AUTHZ_SVN_RECURSIVE,
r->pool)) {
@@ -586,7 +957,7 @@
if (dest_repos_path) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Access denied: - %s %s %s",
- r->method, repos_path, dest_repos_path);
+ r->method, repos_path, dest_repos_path);
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
@@ -595,7 +966,6 @@
}
}
-
return HTTP_FORBIDDEN;
}
@@ -623,11 +993,9 @@
const char *repos_path;
const char *dest_repos_path = NULL;
int status;
-
/* We are not configured to run */
if (!conf->access_file)
return DECLINED;
-
status = req_check_access(r, conf, &repos_path, &dest_repos_path);
if (status == DECLINED) {
if (conf->authoritative) {
@@ -661,16 +1029,31 @@
"Access granted: '%s' %s %s",
r->user, r->method, repos_path);
}
-
return OK;
}
+#ifdef APU_HAS_LDAP
+ static int authz_ldap_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
+ {
+ // make sure that mod_ldap (util_ldap) is loaded
+ if (ap_find_linked_module("util_ldap.c") == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s,
+ "Module mod_ldap missing. Mod_ldap (aka. util_ldap) "
+ "must be loaded in order for mod_authz_svn to function properly with ldap");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ return OK;
+ }
+#endif
/*
* Module flesh
*/
static void register_hooks(apr_pool_t *p)
{
+ #ifdef APU_HAS_LDAP
+ ap_hook_post_config(authz_ldap_post_config,NULL,NULL,APR_HOOK_MIDDLE);
+ #endif
ap_hook_access_checker(access_checker, NULL, NULL, APR_HOOK_LAST);
ap_hook_auth_checker(auth_checker, NULL, NULL, APR_HOOK_FIRST);
}
Regards.
Cong
Le mardi 18 juillet 2006 à 20:30 -0400, Garrett Rooney a écrit :
> On 7/7/06, Ngo Van Cong <van_cong.ngo@int-evry.fr> wrote:
>
> > Another thing that comes to mind is, will this stuff compile if
> > apr-util is compiled without LDAP support? It's important that we not
> > add any extra requirements to mod_authz_svn.
> >
> > I see that in subversion 1.2.3 is already supported apr-util with ldap.
> > And why this stuff is a extra requirements to mod_authz_svn?
>
> Just because apr-util CAN be compiled with LDAP support does not mean
> it MUST be compiled with LDAP support. It's perfectly reasonable for
> Subversion to run on a system that does not have any LDAP libraries at
> all, and thus any patch to add LDAP support must do so in an optional
> manner.
>
> -garrett
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Jul 28 17:32:52 2006