rsync & ldap authentication

Stefan Nehlsen sn at ParlaNet.de
Wed Feb 12 23:16:55 EST 2003


On Tue, Feb 11, 2003 at 12:25:12PM -0500, Darren Jung wrote:
> Hi,
> 
> I'm trying to get rsync 2.5.6 to authenticate users via openldap-2.0.23.
> I was looking through the mailing list archives and found a patch for
> rsync-2.4.6 that does this for me.  I was just wondering if this is still valid,
> or if there has been a new patch or new implementation that has superceded this
> patch.  Any help would be great.  The message I am referring to is as follows:

Here is the newest (?) version of the
"storing rsyncd authentication secrets in ldap" Patch.

Please don't call it ldap-authentication for rsync :-)

We are using it with 2.5.5 at the moment but 2.5.6 doesn't seem to be a
problem.

There are no bigger changes since the first release.

cu, Stefan
-------------- next part --------------
diff -ur rsync-2.5.0-ori/authenticate.c rsync-2.5.0-patched/authenticate.c
--- rsync-2.5.0-ori/authenticate.c	Fri Nov 30 01:21:07 2001
+++ rsync-2.5.0-patched/authenticate.c	Wed Dec 12 16:16:58 2001
@@ -20,6 +20,11 @@
 /* support rsync authentication */
 #include "rsync.h"
 
+#ifdef WITH_LDAP
+#include <lber.h>
+#include <ldap.h>
+#endif
+
 /***************************************************************************
 encode a buffer using base64 - simple and slow algorithm. null terminates
 the result.
@@ -79,9 +84,23 @@
 	STRUCT_STAT st;
 	int ok = 1;
 	extern int am_root;
+	char *users, *tok;
 
 	if (!fname || !*fname) return 0;
 
+	/* this code was in auth_server() */
+	users = strdup(lp_auth_users(module));
+	if (!users) return 0;
+
+	for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
+		if (fnmatch(tok, user, 0) == 0) break;
+	}
+	free(users);
+
+	if (!tok) {
+		return 0;
+	}
+
 	fd = open(fname,O_RDONLY);
 	if (fd == -1) return 0;
 
@@ -133,6 +152,84 @@
 	return 1;
 }
 
+#ifdef WITH_LDAP
+/* return the secret for a user from the ldap server. maximum length
+   is len. null terminate it */
+static int get_ldap_secret(int module, char *user, char *secret, int len)
+{
+	LDAP *ld;
+	LDAPMessage *result, *entry;
+	char *attrs[2], *dn, **vals;
+	char filter[512], *c;
+	char *group=lp_ldap_auth_usergroup(module);
+	int l=0, ok=0;
+
+	/* password attribute to get as result */
+	attrs[0]=lp_ldap_passwd_attribute(module); attrs[1]=NULL;
+
+	/* find nasty character in user that would mess up the ldap filter */
+	for (c="()!&|*=<>~"; *c; c++) {
+		if (strchr(user, *c)) {
+			return 0;
+		}
+	}
+
+	/*   $filter=&lp_ldap_filter($module))=~s/%u/$user/g; :-) */
+	memset(filter, 0, sizeof(filter));
+	for (c=lp_ldap_filter(module); *c && l < sizeof(filter) - 1; c++) {
+		if (*c=='%' && *(c+1)=='u') {
+			char *b;
+			for (b=user; *b && l < sizeof(filter) - 1; b++) {
+				filter[l++]=*b;
+			}
+			c++;
+		} else {
+			filter[l++]=*c;
+		}
+	}
+
+	if ((ld=ldap_init(lp_ldap_server(), lp_ldap_port())) == NULL) {
+		rprintf(FERROR,"ldap: init failed (%s:%d)\n", lp_ldap_server(), lp_ldap_port());
+	} else {
+		if (ldap_simple_bind_s(ld, lp_ldap_root(), lp_ldap_root_passwd()) != LDAP_SUCCESS) {
+			rprintf(FERROR,"ldap: bind failed %s\n", lp_ldap_root());
+	} else {
+		if (ldap_search_s(ld, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result) != LDAP_SUCCESS) {
+			rprintf(FERROR,"ldap: search_s failed\n");
+	} else {
+		if (!(entry=ldap_first_entry(ld, result))) {
+			rprintf(FERROR,"ldap: first_entry failed or no user found\n");
+	} else {
+		if (!(dn=ldap_get_dn(ld, entry))) {
+			rprintf(FERROR,"ldap: get_dn failed\n");
+	} else {
+		if (ldap_compare_s(ld, group, lp_ldap_auth_users_attribute(module), dn) != LDAP_COMPARE_TRUE) {
+			rprintf(FERROR,"ldap: compare_s failed or \"%s\" is not member of \"%s\"\n", dn, group);
+	} else {
+		if (!(vals=ldap_get_values(ld, result, attrs[0])) || !vals[0] || vals[1]) {
+			rprintf(FERROR,"ldap: \"%s\" has no valid password\n", dn);
+			if (vals) ldap_value_free(vals);
+	} else {
+		memset(secret, 0, sizeof(secret)); /* paranoid */
+		strlcpy(secret, vals[0], len);
+		ok=1;
+		ldap_value_free(vals);
+	} /* get_values */
+	} /* compare_s */
+		free(dn);
+	} /* get_dn */
+		ldap_msgfree(entry);
+	} /* first_entry */
+		ldap_msgfree(result);
+	} /* search */
+	} /* bind */
+	} /* init */
+	ldap_unbind(ld);
+
+	return ok;
+}
+#endif
+
 static char *getpassf(char *filename)
 {
 	char buffer[100];
@@ -206,6 +303,7 @@
 char *auth_server(int fd, int module, char *addr, char *leader)
 {
 	char *users = lp_auth_users(module);
+	char *group = lp_ldap_auth_usergroup(module);
 	char challenge[16];
 	char b64_challenge[30];
 	char line[MAXPATHLEN];
@@ -213,10 +311,19 @@
 	char secret[100];
 	char pass[30];
 	char pass2[30];
-	char *tok;
 
 	/* if no auth list then allow anyone in! */
-	if (!users || !*users) return "";
+#ifdef WITH_LDAP
+	if ((!users || !*users) && (!group || !*group)) return "";
+#else
+	if (!users || !*users) {
+		if (group && *group) {
+			rprintf(FERROR,"no ldap support: unset \"ldap auth usergroup\" for anonymous access\n");
+			return NULL;
+		}
+		return "";
+	}
+#endif
 
 	gen_challenge(addr, challenge);
 	
@@ -234,24 +341,39 @@
 	if (sscanf(line,"%99s %29s", user, pass) != 2) {
 		return NULL;
 	}
-	
-	users = strdup(users);
-	if (!users) return NULL;
 
-	for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
-		if (fnmatch(tok, user, 0) == 0) break;
+#ifdef WITH_MANGLE_USER
+	/* foreach $pattern (split(/[ ,\t]+/, &lp_mangle_user($module)){ $user=~s/^$pattern//;warn "bla";last} */
+	if (lp_mangle_user(module)) {
+		char *prefix, *tofree;
+		prefix = tofree = strdup(lp_mangle_user(module));
+		if(!prefix) return NULL; /* strdup may fail */
+		for (prefix=strtok(prefix, " ,\t"); prefix; prefix=strtok(NULL, " ,\t")) {
+			if (strstr(user, prefix) == user) {
+				char *p = user + strlen(prefix);
+				rprintf(FINFO,"mangle user: rewriting \"%s\" to \"%s\"\n", user, p);
+				memmove(user, p, strlen(p) + 1);
+				break;
+			}
+		}
+		free(tofree);
 	}
-	free(users);
+#endif
+	/* checking if user is in "auth users" now happens in get_secret() */
 
-	if (!tok) {
+	memset(secret, 0, sizeof(secret));
+#ifdef WITH_LDAP
+	if (!(users && *users && get_secret(module, user, secret, sizeof(secret)-1) ||
+		group && *group && get_ldap_secret(module, user, secret, sizeof(secret)-1))) {
+		memset(secret, 0, sizeof(secret));
 		return NULL;
 	}
-	
-	memset(secret, 0, sizeof(secret));
+#else
 	if (!get_secret(module, user, secret, sizeof(secret)-1)) {
 		memset(secret, 0, sizeof(secret));
 		return NULL;
 	}
+#endif
 
 	generate_hash(secret, b64_challenge, pass2);
 	memset(secret, 0, sizeof(secret));
@@ -261,7 +383,6 @@
 
 	return NULL;
 }
-
 
 void auth_client(int fd, char *user, char *challenge)
 {
diff -ur rsync-2.5.0-ori/loadparm.c rsync-2.5.0-patched/loadparm.c
--- rsync-2.5.0-ori/loadparm.c	Fri Nov 30 01:21:08 2001
+++ rsync-2.5.0-patched/loadparm.c	Wed Dec 12 15:56:07 2001
@@ -49,6 +49,12 @@
  */
 
 #include "rsync.h"
+
+#ifdef WITH_LDAP
+#include <lber.h>
+#include <ldap.h>
+#endif
+
 #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
 #define strequal(a,b) (strcasecmp(a,b)==0)
 #define BOOLSTR(b) ((b) ? "Yes" : "No")
@@ -101,6 +107,11 @@
 	char *pid_file;
 	int syslog_facility;
 	char *socket_options;
+	char *ldap_server;
+	int ldap_port;
+	char *ldap_root;
+	char *ldap_root_passwd;
+	char *ldap_suffix;
 } global;
 
 static global Globals;
@@ -138,6 +149,13 @@
 	int timeout;
 	int max_connections;
 	BOOL ignore_nonreadable;
+	char *ldap_filter;
+	char *ldap_passwd_attribute;
+	char *ldap_auth_usergroup;
+	char *ldap_auth_users_attribute;
+#ifdef  WITH_MANGLE_USER
+	char *mangle_user;
+#endif
 } service;
 
 
@@ -169,7 +187,15 @@
 	"*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",    /* dont compress */
 	0,        /* timeout */
 	0,        /* max connections */
-	False     /* ignore nonreadable */
+	False,    /* ignore nonreadable */
+	NULL,     /* ldap filter */
+	NULL,     /* ldap passwd attribute */
+	NULL,     /* ldap auth usergroup */
+	"uniquemember" /* ldap auth users attribute */
+#ifdef WITH_MANGLE_USER
+	,
+	NULL      /* mangle user */
+#endif
 };
 
 
@@ -257,6 +283,11 @@
   {"socket options",   P_STRING,  P_GLOBAL, &Globals.socket_options,NULL,  0},
   {"log file",         P_STRING,  P_GLOBAL, &Globals.log_file,      NULL,  0},
   {"pid file",         P_STRING,  P_GLOBAL, &Globals.pid_file,      NULL,  0},
+  {"ldap server",      P_STRING,  P_GLOBAL, &Globals.ldap_server,   NULL,  0},
+  {"ldap port",        P_INTEGER, P_GLOBAL, &Globals.ldap_port,     NULL,  0},
+  {"ldap root",        P_STRING,  P_GLOBAL, &Globals.ldap_root,     NULL,  0},
+  {"ldap root passwd", P_STRING,  P_GLOBAL, &Globals.ldap_root_passwd,NULL,0},
+  {"ldap suffix",      P_STRING,  P_GLOBAL, &Globals.ldap_suffix,   NULL,  0},
 
   {"timeout",          P_INTEGER, P_LOCAL,  &sDefault.timeout,     NULL,  0},
   {"max connections",  P_INTEGER, P_LOCAL,  &sDefault.max_connections,NULL, 0},
@@ -284,6 +315,13 @@
   {"log format",       P_STRING,  P_LOCAL,  &sDefault.log_format,  NULL,   0},
   {"refuse options",   P_STRING,  P_LOCAL,  &sDefault.refuse_options,NULL, 0},
   {"dont compress",    P_STRING,  P_LOCAL,  &sDefault.dont_compress,NULL,  0},
+  {"ldap filter",      P_STRING,  P_LOCAL,  &sDefault.ldap_filter, NULL,   0},
+  {"ldap passwd attribute",P_STRING,P_LOCAL,&sDefault.ldap_passwd_attribute,NULL,0},
+  {"ldap auth usergroup",P_STRING,P_LOCAL,  &sDefault.ldap_auth_usergroup, NULL,0},
+  {"ldap auth users attribute",P_STRING,P_LOCAL,&sDefault.ldap_auth_users_attribute, NULL,0},
+#ifdef WITH_MANGLE_USER
+  {"mangle user",      P_STRING,  P_LOCAL,  &sDefault.mangle_user, NULL,   0},
+#endif
   {NULL,               P_BOOL,    P_NONE,   NULL,                  NULL,   0}
 };
 
@@ -297,6 +335,9 @@
 #ifdef LOG_DAEMON
 	Globals.syslog_facility = LOG_DAEMON;
 #endif
+#ifdef WITH_LDAP
+	Globals.ldap_port = LDAP_PORT;
+#endif
 }
 
 /***************************************************************************
@@ -363,6 +404,21 @@
 FN_LOCAL_STRING(lp_dont_compress, dont_compress)
 FN_LOCAL_INTEGER(lp_timeout, timeout)
 FN_LOCAL_INTEGER(lp_max_connections, max_connections)
+
+FN_GLOBAL_STRING(lp_ldap_server, &Globals.ldap_server)
+FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
+FN_GLOBAL_STRING(lp_ldap_root, &Globals.ldap_root)
+FN_GLOBAL_STRING(lp_ldap_root_passwd, &Globals.ldap_root_passwd)
+FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.ldap_suffix)
+
+FN_LOCAL_STRING(lp_ldap_filter, ldap_filter)
+FN_LOCAL_STRING(lp_ldap_passwd_attribute, ldap_passwd_attribute)
+FN_LOCAL_STRING(lp_ldap_auth_usergroup, ldap_auth_usergroup)
+FN_LOCAL_STRING(lp_ldap_auth_users_attribute, ldap_auth_users_attribute)
+
+#ifdef WITH_MANGLE_USER
+FN_LOCAL_STRING(lp_mangle_user, mangle_user)
+#endif
 
 /* local prototypes */
 static int    strwicmp( char *psz1, char *psz2 );


More information about the rsync mailing list