00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "rsync.h"
00025
00026
00027 static int match_hostname(char *host, char *tok)
00028 {
00029 if (!host || !*host)
00030 return 0;
00031 return wildmatch(tok, host);
00032 }
00033
00034 static int match_binary(char *b1, char *b2, char *mask, int addrlen)
00035 {
00036 int i;
00037
00038 for (i = 0; i < addrlen; i++) {
00039 if ((b1[i] ^ b2[i]) & mask[i])
00040 return 0;
00041 }
00042
00043 return 1;
00044 }
00045
00046 static void make_mask(char *mask, int plen, int addrlen)
00047 {
00048 int w, b;
00049
00050 w = plen >> 3;
00051 b = plen & 0x7;
00052
00053 if (w)
00054 memset(mask, 0xff, w);
00055 if (w < addrlen)
00056 mask[w] = 0xff & (0xff<<(8-b));
00057 if (w+1 < addrlen)
00058 memset(mask+w+1, 0, addrlen-w-1);
00059
00060 return;
00061 }
00062
00063 static int match_address(char *addr, char *tok)
00064 {
00065 char *p;
00066 struct addrinfo hints, *resa, *rest;
00067 int gai;
00068 int ret = 0;
00069 int addrlen = 0;
00070 #ifdef HAVE_STRTOL
00071 long int bits;
00072 #else
00073 int bits;
00074 #endif
00075 char mask[16];
00076 char *a = NULL, *t = NULL;
00077 unsigned int len;
00078
00079 if (!addr || !*addr)
00080 return 0;
00081
00082 p = strchr(tok,'/');
00083 if (p) {
00084 *p = '\0';
00085 len = p - tok;
00086 } else
00087 len = strlen(tok);
00088
00089
00090 if (strspn(tok, ".0123456789") != len
00091 #ifdef INET6
00092 && strchr(tok, ':') == NULL
00093 #endif
00094 ) {
00095 if (p)
00096 *p = '/';
00097 return 0;
00098 }
00099
00100 memset(&hints, 0, sizeof(hints));
00101 hints.ai_family = PF_UNSPEC;
00102 hints.ai_socktype = SOCK_STREAM;
00103 #ifdef AI_NUMERICHOST
00104 hints.ai_flags = AI_NUMERICHOST;
00105 #endif
00106
00107 if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
00108 if (p)
00109 *p = '/';
00110 return 0;
00111 }
00112
00113 gai = getaddrinfo(tok, NULL, &hints, &rest);
00114 if (p)
00115 *p++ = '/';
00116 if (gai != 0) {
00117 rprintf(FLOG, "error matching address %s: %s\n",
00118 tok, gai_strerror(gai));
00119 freeaddrinfo(resa);
00120 return 0;
00121 }
00122
00123 if (rest->ai_family != resa->ai_family) {
00124 ret = 0;
00125 goto out;
00126 }
00127
00128 switch(resa->ai_family) {
00129 case PF_INET:
00130 a = (char *)&((struct sockaddr_in *)resa->ai_addr)->sin_addr;
00131 t = (char *)&((struct sockaddr_in *)rest->ai_addr)->sin_addr;
00132 addrlen = 4;
00133
00134 break;
00135
00136 #ifdef INET6
00137 case PF_INET6:
00138 {
00139 struct sockaddr_in6 *sin6a, *sin6t;
00140
00141 sin6a = (struct sockaddr_in6 *)resa->ai_addr;
00142 sin6t = (struct sockaddr_in6 *)rest->ai_addr;
00143
00144 a = (char *)&sin6a->sin6_addr;
00145 t = (char *)&sin6t->sin6_addr;
00146
00147 addrlen = 16;
00148
00149 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
00150 if (sin6t->sin6_scope_id &&
00151 sin6a->sin6_scope_id != sin6t->sin6_scope_id) {
00152 ret = 0;
00153 goto out;
00154 }
00155 #endif
00156
00157 break;
00158 }
00159 #endif
00160 default:
00161 rprintf(FLOG, "unknown family %u\n", rest->ai_family);
00162 ret = 0;
00163 goto out;
00164 }
00165
00166 bits = -1;
00167 if (p) {
00168 if (inet_pton(resa->ai_addr->sa_family, p, mask) <= 0) {
00169 #ifdef HAVE_STRTOL
00170 char *ep = NULL;
00171 #else
00172 unsigned char *pp;
00173 #endif
00174
00175 #ifdef HAVE_STRTOL
00176 bits = strtol(p, &ep, 10);
00177 if (!*p || *ep) {
00178 rprintf(FLOG, "malformed mask in %s\n", tok);
00179 ret = 0;
00180 goto out;
00181 }
00182 #else
00183 for (pp = (unsigned char *)p; *pp; pp++) {
00184 if (!isascii(*pp) || !isdigit(*pp)) {
00185 rprintf(FLOG, "malformed mask in %s\n", tok);
00186 ret = 0;
00187 goto out;
00188 }
00189 }
00190 bits = atoi(p);
00191 #endif
00192 if (bits == 0) {
00193 ret = 1;
00194 goto out;
00195 }
00196 if (bits < 0 || bits > (addrlen << 3)) {
00197 rprintf(FLOG, "malformed mask in %s\n", tok);
00198 ret = 0;
00199 goto out;
00200 }
00201 }
00202 } else {
00203 bits = 128;
00204 }
00205
00206 if (bits >= 0)
00207 make_mask(mask, bits, addrlen);
00208
00209 ret = match_binary(a, t, mask, addrlen);
00210
00211 out:
00212 freeaddrinfo(resa);
00213 freeaddrinfo(rest);
00214 return ret;
00215 }
00216
00217 static int access_match(char *list, char *addr, char *host)
00218 {
00219 char *tok;
00220 char *list2 = strdup(list);
00221
00222 if (!list2)
00223 out_of_memory("access_match");
00224
00225 strlower(list2);
00226 if (host)
00227 strlower(host);
00228
00229 for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
00230 if (match_hostname(host, tok) || match_address(addr, tok)) {
00231 free(list2);
00232 return 1;
00233 }
00234 }
00235
00236 free(list2);
00237 return 0;
00238 }
00239
00240 int allow_access(char *addr, char *host, char *allow_list, char *deny_list)
00241 {
00242 if (allow_list && !*allow_list)
00243 allow_list = NULL;
00244 if (deny_list && !*deny_list)
00245 deny_list = NULL;
00246
00247
00248 if (allow_list) {
00249 if (access_match(allow_list, addr, host))
00250 return 1;
00251
00252 if (!deny_list)
00253 return 0;
00254 }
00255
00256
00257
00258 if (deny_list && access_match(deny_list, addr, host))
00259 return 0;
00260
00261
00262 return 1;
00263 }