/opensource.apple.com/source/rsync/rsync-11/rsync/access.c
C | 268 lines | 209 code | 42 blank | 17 comment | 14 complexity | 7942b457633f60d652a9cf713608da52 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, GPL-2.0, BSD-3-Clause, GPL-3.0, MPL-2.0, LGPL-2.0, LGPL-2.1, CC-BY-SA-3.0, IPL-1.0, ISC, AGPL-1.0, AGPL-3.0, JSON, Apache-2.0, 0BSD
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <title>access.c</title>
- <style type="text/css">
- .enscript-comment { font-style: italic; color: rgb(178,34,34); }
- .enscript-function-name { font-weight: bold; color: rgb(0,0,255); }
- .enscript-variable-name { font-weight: bold; color: rgb(184,134,11); }
- .enscript-keyword { font-weight: bold; color: rgb(160,32,240); }
- .enscript-reference { font-weight: bold; color: rgb(95,158,160); }
- .enscript-string { font-weight: bold; color: rgb(188,143,143); }
- .enscript-builtin { font-weight: bold; color: rgb(218,112,214); }
- .enscript-type { font-weight: bold; color: rgb(34,139,34); }
- .enscript-highlight { text-decoration: underline; color: 0; }
- </style>
- </head>
- <body id="top">
- <h1 style="margin:8px;" id="f1">access.c <span style="font-weight: normal; font-size: 0.5em;">[<a href="?txt">plain text</a>]</span></h1>
- <hr/>
- <div></div>
- <pre>
- <span class="enscript-comment">/*
- 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.
- */</span>
- <span class="enscript-comment">/*
- hosts allow/deny code for rsync
- */</span>
- #<span class="enscript-reference">include</span> <span class="enscript-string">"rsync.h"</span>
- <span class="enscript-type">static</span> <span class="enscript-type">int</span> <span class="enscript-function-name">match_hostname</span>(<span class="enscript-type">char</span> *host, <span class="enscript-type">char</span> *tok)
- {
- <span class="enscript-keyword">if</span> (!host || !*host) <span class="enscript-keyword">return</span> 0;
- <span class="enscript-keyword">return</span> (fnmatch(tok, host, 0) == 0);
- }
- <span class="enscript-type">static</span> <span class="enscript-type">int</span> <span class="enscript-function-name">match_binary</span>(<span class="enscript-type">char</span> *b1, <span class="enscript-type">char</span> *b2, <span class="enscript-type">char</span> *mask, <span class="enscript-type">int</span> addrlen)
- {
- <span class="enscript-type">int</span> i;
- <span class="enscript-keyword">for</span> (i=0; i<addrlen; i++) {
- <span class="enscript-keyword">if</span> ((b1[i]^b2[i])&mask[i]) {
- <span class="enscript-keyword">return</span> 0;
- }
- }
- <span class="enscript-keyword">return</span> 1;
- }
- <span class="enscript-type">static</span> <span class="enscript-type">void</span> <span class="enscript-function-name">make_mask</span>(<span class="enscript-type">char</span> *mask, <span class="enscript-type">int</span> plen, <span class="enscript-type">int</span> addrlen) {
- <span class="enscript-type">int</span> w, b;
- w = plen >> 3;
- b = plen & 0x7;
- <span class="enscript-keyword">if</span> (w)
- memset(mask, 0xff, w);
- <span class="enscript-keyword">if</span> (w < addrlen)
- mask[w] = 0xff & (0xff<<(8-b));
- <span class="enscript-keyword">if</span> (w+1 < addrlen)
- memset(mask+w+1, 0, addrlen-w-1);
- <span class="enscript-keyword">return</span>;
- }
- <span class="enscript-type">static</span> <span class="enscript-type">int</span> <span class="enscript-function-name">match_address</span>(<span class="enscript-type">char</span> *addr, <span class="enscript-type">char</span> *tok)
- {
- <span class="enscript-type">char</span> *p;
- <span class="enscript-type">struct</span> addrinfo hints, *resa, *rest;
- <span class="enscript-type">int</span> gai;
- <span class="enscript-type">int</span> ret = 0;
- <span class="enscript-type">int</span> addrlen = 0;
- #<span class="enscript-reference">ifdef</span> <span class="enscript-variable-name">HAVE_STRTOL</span>
- <span class="enscript-type">long</span> <span class="enscript-type">int</span> bits;
- #<span class="enscript-reference">else</span>
- <span class="enscript-type">int</span> bits;
- #<span class="enscript-reference">endif</span>
- <span class="enscript-type">char</span> mask[16];
- <span class="enscript-type">char</span> *a = NULL, *t = NULL;
- <span class="enscript-keyword">if</span> (!addr || !*addr) <span class="enscript-keyword">return</span> 0;
- p = strchr(tok,<span class="enscript-string">'/'</span>);
- <span class="enscript-keyword">if</span> (p) *p = 0;
- memset(&hints, 0, <span class="enscript-keyword">sizeof</span>(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- #<span class="enscript-reference">ifdef</span> <span class="enscript-variable-name">AI_NUMERICHOST</span>
- hints.ai_flags = AI_NUMERICHOST;
- #<span class="enscript-reference">endif</span>
- gai = getaddrinfo(addr, NULL, &hints, &resa);
- <span class="enscript-keyword">if</span> (gai) <span class="enscript-keyword">return</span> 0;
- gai = getaddrinfo(tok, NULL, &hints, &rest);
- <span class="enscript-keyword">if</span> (p)
- *p++ = <span class="enscript-string">'/'</span>;
- <span class="enscript-keyword">if</span> (gai) {
- rprintf(FERROR,<span class="enscript-string">"malformed address %s\n"</span>, tok);
- freeaddrinfo(resa);
- <span class="enscript-keyword">return</span> 0;
- }
- <span class="enscript-keyword">if</span> (rest->ai_family != resa->ai_family) {
- ret = 0;
- <span class="enscript-keyword">goto</span> <span class="enscript-reference">out</span>;
- }
- <span class="enscript-keyword">switch</span>(resa->ai_family) {
- <span class="enscript-keyword">case</span> <span class="enscript-reference">PF_INET</span>:
- a = (<span class="enscript-type">char</span> *)&((<span class="enscript-type">struct</span> sockaddr_in *)resa->ai_addr)->sin_addr;
- t = (<span class="enscript-type">char</span> *)&((<span class="enscript-type">struct</span> sockaddr_in *)rest->ai_addr)->sin_addr;
- addrlen = 4;
- <span class="enscript-keyword">break</span>;
- #<span class="enscript-reference">ifdef</span> <span class="enscript-variable-name">INET6</span>
- <span class="enscript-keyword">case</span> <span class="enscript-reference">PF_INET6</span>:
- {
- <span class="enscript-type">struct</span> sockaddr_in6 *sin6a, *sin6t;
- sin6a = (<span class="enscript-type">struct</span> sockaddr_in6 *)resa->ai_addr;
- sin6t = (<span class="enscript-type">struct</span> sockaddr_in6 *)rest->ai_addr;
- a = (<span class="enscript-type">char</span> *)&sin6a->sin6_addr;
- t = (<span class="enscript-type">char</span> *)&sin6t->sin6_addr;
- addrlen = 16;
- #<span class="enscript-reference">ifdef</span> <span class="enscript-variable-name">HAVE_SOCKADDR_IN6_SCOPE_ID</span>
- <span class="enscript-keyword">if</span> (sin6t->sin6_scope_id &&
- sin6a->sin6_scope_id != sin6t->sin6_scope_id) {
- ret = 0;
- <span class="enscript-keyword">goto</span> <span class="enscript-reference">out</span>;
- }
- #<span class="enscript-reference">endif</span>
- <span class="enscript-keyword">break</span>;
- }
- #<span class="enscript-reference">endif</span>
- <span class="enscript-reference">default</span>:
- rprintf(FERROR,<span class="enscript-string">"unknown family %u\n"</span>, rest->ai_family);
- ret = 0;
- <span class="enscript-keyword">goto</span> <span class="enscript-reference">out</span>;
- }
- bits = -1;
- <span class="enscript-keyword">if</span> (p) {
- <span class="enscript-keyword">if</span> (inet_pton(resa->ai_addr->sa_family, p, mask) <= 0) {
- #<span class="enscript-reference">ifdef</span> <span class="enscript-variable-name">HAVE_STRTOL</span>
- <span class="enscript-type">char</span> *ep = NULL;
- #<span class="enscript-reference">else</span>
- <span class="enscript-type">unsigned</span> <span class="enscript-type">char</span> *pp;
- #<span class="enscript-reference">endif</span>
- #<span class="enscript-reference">ifdef</span> <span class="enscript-variable-name">HAVE_STRTOL</span>
- bits = strtol(p, &ep, 10);
- <span class="enscript-keyword">if</span> (!*p || *ep) {
- rprintf(FERROR,<span class="enscript-string">"malformed mask in %s\n"</span>, tok);
- ret = 0;
- <span class="enscript-keyword">goto</span> <span class="enscript-reference">out</span>;
- }
- #<span class="enscript-reference">else</span>
- <span class="enscript-keyword">for</span> (pp = (<span class="enscript-type">unsigned</span> <span class="enscript-type">char</span> *)p; *pp; pp++) {
- <span class="enscript-keyword">if</span> (!isascii(*pp) || !isdigit(*pp)) {
- rprintf(FERROR,<span class="enscript-string">"malformed mask in %s\n"</span>, tok);
- ret = 0;
- <span class="enscript-keyword">goto</span> <span class="enscript-reference">out</span>;
- }
- }
- bits = atoi(p);
- #<span class="enscript-reference">endif</span>
- <span class="enscript-keyword">if</span> (bits == 0) {
- ret = 1;
- <span class="enscript-keyword">goto</span> <span class="enscript-reference">out</span>;
- }
- <span class="enscript-keyword">if</span> (bits < 0 || bits > (addrlen << 3)) {
- rprintf(FERROR,<span class="enscript-string">"malformed mask in %s\n"</span>, tok);
- ret = 0;
- <span class="enscript-keyword">goto</span> <span class="enscript-reference">out</span>;
- }
- }
- } <span class="enscript-keyword">else</span> {
- bits = 128;
- }
- <span class="enscript-keyword">if</span> (bits >= 0)
- make_mask(mask, bits, addrlen);
- ret = match_binary(a, t, mask, addrlen);
- <span class="enscript-reference">out</span>:
- freeaddrinfo(resa);
- freeaddrinfo(rest);
- <span class="enscript-keyword">return</span> ret;
- }
- <span class="enscript-type">static</span> <span class="enscript-type">int</span> <span class="enscript-function-name">access_match</span>(<span class="enscript-type">char</span> *list, <span class="enscript-type">char</span> *addr, <span class="enscript-type">char</span> *host)
- {
- <span class="enscript-type">char</span> *tok;
- <span class="enscript-type">char</span> *list2 = strdup(list);
- <span class="enscript-keyword">if</span> (!list2) out_of_memory(<span class="enscript-string">"access_match"</span>);
- strlower(list2);
- <span class="enscript-keyword">if</span> (host) strlower(host);
- <span class="enscript-keyword">for</span> (tok=strtok(list2,<span class="enscript-string">" ,\t"</span>); tok; tok=strtok(NULL,<span class="enscript-string">" ,\t"</span>)) {
- <span class="enscript-keyword">if</span> (match_hostname(host, tok) || match_address(addr, tok)) {
- free(list2);
- <span class="enscript-keyword">return</span> 1;
- }
- }
- free(list2);
- <span class="enscript-keyword">return</span> 0;
- }
- <span class="enscript-type">int</span> <span class="enscript-function-name">allow_access</span>(<span class="enscript-type">char</span> *addr, <span class="enscript-type">char</span> *host, <span class="enscript-type">char</span> *allow_list, <span class="enscript-type">char</span> *deny_list)
- {
- <span class="enscript-comment">/* if theres no deny list and no allow list then allow access */</span>
- <span class="enscript-keyword">if</span> ((!deny_list || !*deny_list) && (!allow_list || !*allow_list))
- <span class="enscript-keyword">return</span> 1;
- <span class="enscript-comment">/* if there is an allow list but no deny list then allow only hosts
- on the allow list */</span>
- <span class="enscript-keyword">if</span> (!deny_list || !*deny_list)
- <span class="enscript-keyword">return</span>(access_match(allow_list, addr, host));
- <span class="enscript-comment">/* if theres a deny list but no allow list then allow
- all hosts not on the deny list */</span>
- <span class="enscript-keyword">if</span> (!allow_list || !*allow_list)
- <span class="enscript-keyword">return</span>(!access_match(deny_list,addr,host));
- <span class="enscript-comment">/* if there are both type of list then allow all hosts on the
- allow list */</span>
- <span class="enscript-keyword">if</span> (access_match(allow_list,addr,host))
- <span class="enscript-keyword">return</span> 1;
- <span class="enscript-comment">/* if there are both type of list and it's not on the allow then
- allow it if its not on the deny */</span>
- <span class="enscript-keyword">if</span> (access_match(deny_list,addr,host))
- <span class="enscript-keyword">return</span> 0;
- <span class="enscript-keyword">return</span> 1;
- }
- </pre>
- <hr />
- </body></html>