2 Copyright (C) Andrew Tridgell 1998
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 hosts allow/deny code for rsync
27 static int match_hostname(char *host
, char *tok
)
29 if (!host
|| !*host
) return 0;
30 return (fnmatch(tok
, host
, 0) == 0);
33 static int match_binary(char *b1
, char *b2
, char *mask
, int addrlen
)
37 for (i
=0; i
<addrlen
; i
++) {
38 if ((b1
[i
]^b2
[i
])&mask
[i
]) {
46 static void make_mask(char *mask
, int plen
, int addrlen
) {
53 memset(mask
, 0xff, w
);
55 mask
[w
] = 0xff & (0xff<<(8-b
));
57 memset(mask
+w
+1, 0, addrlen
-w
-1);
62 static int match_address(char *addr
, char *tok
)
65 struct addrinfo hints
, *resa
, *rest
;
75 char *a
= NULL
, *t
= NULL
;
77 if (!addr
|| !*addr
) return 0;
82 /* skip if last char is not a digit (i.e. not an address) */
83 /* (don't check first char - might be 11.22.33.44.an.isp) */
84 if (!*tok
) return 0; /* nothing to check */
85 if (!isdigit(*(unsigned char*)tok
+strlen(tok
)-1)) return 0;
87 memset(&hints
, 0, sizeof(hints
));
88 hints
.ai_family
= PF_UNSPEC
;
89 hints
.ai_socktype
= SOCK_STREAM
;
91 hints
.ai_flags
= AI_NUMERICHOST
;
94 gai
= getaddrinfo(addr
, NULL
, &hints
, &resa
);
97 gai
= getaddrinfo(tok
, NULL
, &hints
, &rest
);
101 rprintf(FERROR
,"malformed address %s\n", tok
);
106 if (rest
->ai_family
!= resa
->ai_family
) {
111 switch(resa
->ai_family
) {
113 a
= (char *)&((struct sockaddr_in
*)resa
->ai_addr
)->sin_addr
;
114 t
= (char *)&((struct sockaddr_in
*)rest
->ai_addr
)->sin_addr
;
122 struct sockaddr_in6
*sin6a
, *sin6t
;
124 sin6a
= (struct sockaddr_in6
*)resa
->ai_addr
;
125 sin6t
= (struct sockaddr_in6
*)rest
->ai_addr
;
127 a
= (char *)&sin6a
->sin6_addr
;
128 t
= (char *)&sin6t
->sin6_addr
;
132 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
133 if (sin6t
->sin6_scope_id
&&
134 sin6a
->sin6_scope_id
!= sin6t
->sin6_scope_id
) {
144 rprintf(FERROR
,"unknown family %u\n", rest
->ai_family
);
151 if (inet_pton(resa
->ai_addr
->sa_family
, p
, mask
) <= 0) {
159 bits
= strtol(p
, &ep
, 10);
161 rprintf(FERROR
,"malformed mask in %s\n", tok
);
166 for (pp
= (unsigned char *)p
; *pp
; pp
++) {
167 if (!isascii(*pp
) || !isdigit(*pp
)) {
168 rprintf(FERROR
,"malformed mask in %s\n", tok
);
179 if (bits
< 0 || bits
> (addrlen
<< 3)) {
180 rprintf(FERROR
,"malformed mask in %s\n", tok
);
190 make_mask(mask
, bits
, addrlen
);
192 ret
= match_binary(a
, t
, mask
, addrlen
);
200 static int access_match(char *list
, char *addr
, char *host
)
203 char *list2
= strdup(list
);
205 if (!list2
) out_of_memory("access_match");
208 if (host
) strlower(host
);
210 for (tok
=strtok(list2
," ,\t"); tok
; tok
=strtok(NULL
," ,\t")) {
211 if (match_hostname(host
, tok
) || match_address(addr
, tok
)) {
221 int allow_access(char *addr
, char *host
, char *allow_list
, char *deny_list
)
223 /* if theres no deny list and no allow list then allow access */
224 if ((!deny_list
|| !*deny_list
) && (!allow_list
|| !*allow_list
))
227 /* if there is an allow list but no deny list then allow only hosts
229 if (!deny_list
|| !*deny_list
)
230 return(access_match(allow_list
, addr
, host
));
232 /* if theres a deny list but no allow list then allow
233 all hosts not on the deny list */
234 if (!allow_list
|| !*allow_list
)
235 return(!access_match(deny_list
,addr
,host
));
237 /* if there are both type of list then allow all hosts on the
239 if (access_match(allow_list
,addr
,host
))
242 /* if there are both type of list and it's not on the allow then
243 allow it if its not on the deny */
244 if (access_match(deny_list
,addr
,host
))