added hosts allow and hosts deny support. I ended up writing my own as
authorAndrew Tridgell <tridge@samba.org>
Wed, 13 May 1998 08:03:47 +0000 (08:03 +0000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 13 May 1998 08:03:47 +0000 (08:03 +0000)
the tcpd code is not quite what I wanted.

Makefile.in
access.c [new file with mode: 0644]
clientserver.c
loadparm.c

index f1e94a6562ea83bf814ddc431538a09d42d40c79..437851501c788249f1171d449e679395ab34b8cc 100644 (file)
@@ -23,7 +23,7 @@ SHELL=/bin/sh
 LIBOBJ=lib/getopt.o lib/fnmatch.o lib/zlib.o lib/compat.o
 OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o log.o
 OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o 
-DAEMON_OBJ = params.o loadparm.o clientserver.o
+DAEMON_OBJ = params.o loadparm.o clientserver.o access.o
 OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ)
 
 # note that the -I. is needed to handle config.h when using VPATH
diff --git a/access.c b/access.c
new file mode 100644 (file)
index 0000000..f1a8bd7
--- /dev/null
+++ b/access.c
@@ -0,0 +1,127 @@
+/* 
+   Copyright (C) Andrew Tridgell 1998
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+  hosts allow/deny code for rsync
+
+  */
+
+#include "rsync.h"
+
+
+static int match_hostname(char *host, char *tok)
+{
+       if (!host || !*host) return 0;
+       return (fnmatch(tok, host, 0) == 0);
+}
+
+
+static int match_address(char *addr, char *tok)
+{
+       char *p;
+       unsigned long a, t, mask = ~0;
+
+       if (!addr || !*addr) return 0;
+
+       if (!isdigit(tok[0])) return 0;
+
+       p = strchr(tok,'/');
+       if (p) *p = 0;
+
+       a = inet_addr(addr);
+       t = inet_addr(tok);
+
+       if (p) {
+               *p = '/';
+       }
+
+       if (t == INADDR_NONE) {
+               rprintf(FERROR,"malformed address %s\n", tok);
+               return 0;
+       }
+
+       a = ntohl(a);
+       t = ntohl(t);
+
+       if (p) {
+               if (strchr(p+1,'.')) {
+                       mask = inet_addr(p+1);
+                       if (mask == INADDR_NONE) {
+                               rprintf(FERROR,"malformed mask in %s\n", tok);
+                               return 0;
+                       }
+                       mask = ntohl(mask);
+               } else {
+                       int bits = atoi(p+1);
+                       if (bits <= 0 || bits > 32) {
+                               rprintf(FERROR,"malformed mask in %s\n", tok);
+                               return 0;
+                       }
+                       mask &= (mask << (32-bits));
+               }
+       }
+
+       return ((a&mask) == (t&mask));
+}
+
+static int access_match(char *list, char *addr, char *host)
+{
+       char *tok;
+       char *list2 = strdup(list);
+
+       if (!list2) out_of_memory("access_match");
+
+       for (tok=strtok(list2," ,\t"); tok; tok=strtok(NULL," ,\t")) {
+               if (match_hostname(host, tok) || match_address(addr, tok)) {
+                       free(list2);
+                       return 1;
+               }
+       }
+
+       free(list2);
+       return 0;
+}
+
+int allow_access(char *addr, char *host, char *allow_list, char *deny_list)
+{
+       /* if theres no deny list and no allow list then allow access */
+       if ((!deny_list || !*deny_list) && (!allow_list || !*allow_list))
+               return 1;
+
+       /* if there is an allow list but no deny list then allow only hosts
+          on the allow list */
+       if (!deny_list || !*deny_list)
+               return(access_match(allow_list, addr, host));
+
+       /* if theres a deny list but no allow list then allow
+          all hosts not on the deny list */
+       if (!allow_list || !*allow_list)
+               return(!access_match(deny_list,addr,host));
+
+       /* if there are both type of list then allow all hosts on the
+           allow list */
+       if (access_match(allow_list,addr,host))
+               return 1;
+
+       /* if there are both type of list and it's not on the allow then
+          allow it if its not on the deny */
+       if (access_match(deny_list,addr,host))
+               return 0;
+
+       return 1;
+}
index 62d049d73f6d3d9b4bc12ea0764a75288e77033a..32deee7633ef67107121c43dbc9a99217c5f98e3 100644 (file)
@@ -99,9 +99,17 @@ static int rsync_module(int fd, int i)
        uid_t uid;
        gid_t gid;
        char *p;
+       char *addr = client_addr(fd);
+       char *host = client_name(fd);
+
+       if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
+               rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
+                       lp_name(i), client_name(fd), client_addr(fd));
+               return -1;
+       }
 
        rprintf(FINFO,"rsync on module %s from %s (%s)\n",
-               lp_name(i), client_name(fd), client_addr(fd));
+               lp_name(i), host, addr);
 
        module_id = i;
 
index 7fff24f05b0d792416c256484d260cb54c5c4a08..38c539c772073c5bbcda5cc8e78e3e362cc946f0 100644 (file)
@@ -116,6 +116,8 @@ typedef struct
        BOOL list;
        char *uid;
        char *gid;
+       char *hosts_allow;
+       char *hosts_deny;
 } service;
 
 
@@ -129,6 +131,8 @@ static service sDefault =
        True,    /* list */
        "nobody",/* uid */
        "nobody",/* gid */
+       NULL,    /* hosts allow */
+       NULL,    /* hosts deny */
 };
 
 
@@ -153,6 +157,8 @@ static struct parm_struct parm_table[] =
   {"list",             P_BOOL,    P_LOCAL,  &sDefault.list,        NULL,   0},
   {"uid",              P_STRING,  P_LOCAL,  &sDefault.uid,         NULL,   0},
   {"gid",              P_STRING,  P_LOCAL,  &sDefault.gid,         NULL,   0},
+  {"hosts allow",      P_STRING,  P_LOCAL,  &sDefault.hosts_allow, NULL,   0},
+  {"hosts deny",       P_STRING,  P_LOCAL,  &sDefault.hosts_deny,  NULL,   0},
   {NULL,               P_BOOL,    P_NONE,   NULL,                  NULL,   0}
 };
 
@@ -204,6 +210,8 @@ FN_LOCAL_BOOL(lp_read_only, read_only)
 FN_LOCAL_BOOL(lp_list, list)
 FN_LOCAL_STRING(lp_uid, uid)
 FN_LOCAL_STRING(lp_gid, gid)
+FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
+FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
 
 /* local prototypes */
 static int    strwicmp( char *psz1, char *psz2 );