Storing rsync secrets in LDAP

Darren Jung darren at web-services.net
Sat May 3 01:44:57 EST 2003


Hi, a few months ago I posted a message about using LDAP to store rsync secrets in LDAP.  I received a response about patching the rsync source code with a patch file.  I am now finally getting around to doing this, and when I tried to use the patch command 'patch --verbose ./rsync-2.5.6/authenticate.c rsync-ldap.patch' , it gives me the following error:

Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|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
--------------------------
Patching file ./rsync-2.5.0/authenticate.c using Plan A...
Hunk #1 succeeded at 20.
Hunk #2 FAILED at 84.
Hunk #3 FAILED at 303.
patch: **** malformed patch at line 70:


I was wondering if someone could tell me how to implement the patch, it would be great (as in the proper patch command or another method of patching).  I am including the transcript of the message from a few months ago for reference.

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

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 );

-- 
To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.tuxedo.org/~esr/faqs/smart-questions.html


Thanks, 

Darren



More information about the rsync mailing list