access.c

説明を見る。
00001 /* 
00002    Copyright (C) Andrew Tridgell 1998
00003    
00004    This program is free software; you can redistribute it and/or modify
00005    it under the terms of the GNU General Public License as published by
00006    the Free Software Foundation; either version 2 of the License, or
00007    (at your option) any later version.
00008    
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013    
00014    You should have received a copy of the GNU General Public License
00015    along with this program; if not, write to the Free Software
00016    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 */
00018 
00019 /*
00020   hosts allow/deny code for rsync
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         /* Fail quietly if tok is a hostname (not an address) */
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         /* If we match an allow-list item, we always allow access. */
00248         if (allow_list) {
00249                 if (access_match(allow_list, addr, host))
00250                         return 1;
00251                 /* For an allow-list w/o a deny-list, disallow non-matches. */
00252                 if (!deny_list)
00253                         return 0;
00254         }
00255 
00256         /* If we match a deny-list item (and got past any allow-list
00257          * items), we always disallow access. */
00258         if (deny_list && access_match(deny_list, addr, host))
00259                 return 0;
00260 
00261         /* Allow all other access. */
00262         return 1;
00263 }

rsyncに対してSat Dec 5 19:45:40 2009に生成されました。  doxygen 1.4.7