Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : check access rules for socket connections
5 :
6 : Copyright (C) Andrew Tridgell 2004
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 :
23 : /*
24 : This module is an adaption of code from the tcpd-1.4 package written
25 : by Wietse Venema, Eindhoven University of Technology, The Netherlands.
26 :
27 : The code is used here with permission.
28 :
29 : The code has been considerably changed from the original. Bug reports
30 : should be sent to samba-technical@lists.samba.org
31 : */
32 :
33 : #include "includes.h"
34 : #include "system/network.h"
35 : #include "lib/socket/socket.h"
36 : #include "lib/util/util_net.h"
37 : #include "lib/util/access.h"
38 :
39 : /* return true if the char* contains ip addrs only. Used to avoid
40 : gethostbyaddr() calls */
41 :
42 0 : static bool only_ipaddrs_in_list(const char** list)
43 : {
44 0 : bool only_ip = true;
45 :
46 0 : if (!list)
47 0 : return true;
48 :
49 0 : for (; *list ; list++) {
50 : /* factor out the special strings */
51 0 : if (strcmp(*list, "ALL")==0 ||
52 0 : strcmp(*list, "FAIL")==0 ||
53 0 : strcmp(*list, "EXCEPT")==0) {
54 0 : continue;
55 : }
56 :
57 0 : if (!is_ipaddress(*list)) {
58 : /*
59 : * if we failed, make sure that it was not because the token
60 : * was a network/netmask pair. Only network/netmask pairs
61 : * have a '/' in them
62 : */
63 0 : if ((strchr(*list, '/')) == NULL) {
64 0 : only_ip = false;
65 0 : DEBUG(3,("only_ipaddrs_in_list: list has non-ip address (%s)\n", *list));
66 0 : break;
67 : }
68 : }
69 : }
70 :
71 0 : return only_ip;
72 : }
73 :
74 : /* return true if access should be allowed to a service for a socket */
75 96518 : bool socket_check_access(struct socket_context *sock,
76 : const char *service_name,
77 : const char **allow_list, const char **deny_list)
78 : {
79 : bool ret;
80 96518 : const char *name="";
81 : struct socket_address *addr;
82 : TALLOC_CTX *mem_ctx;
83 :
84 96518 : if ((!deny_list || *deny_list==0) &&
85 0 : (!allow_list || *allow_list==0)) {
86 96518 : return true;
87 : }
88 :
89 0 : mem_ctx = talloc_init("socket_check_access");
90 0 : if (!mem_ctx) {
91 0 : return false;
92 : }
93 :
94 0 : addr = socket_get_peer_addr(sock, mem_ctx);
95 0 : if (!addr) {
96 0 : DEBUG(0,("socket_check_access: Denied connection from unknown host: could not get peer address from kernel\n"));
97 0 : talloc_free(mem_ctx);
98 0 : return false;
99 : }
100 :
101 : /* bypass gethostbyaddr() calls if the lists only contain IP addrs */
102 0 : if (!only_ipaddrs_in_list(allow_list) ||
103 0 : !only_ipaddrs_in_list(deny_list)) {
104 0 : name = socket_get_peer_name(sock, mem_ctx);
105 0 : if (!name) {
106 0 : name = addr->addr;
107 : }
108 : }
109 :
110 0 : if (!addr) {
111 0 : DEBUG(0,("socket_check_access: Denied connection from unknown host\n"));
112 0 : talloc_free(mem_ctx);
113 0 : return false;
114 : }
115 :
116 0 : ret = allow_access(deny_list, allow_list, name, addr->addr);
117 :
118 0 : if (ret) {
119 0 : DEBUG(2,("socket_check_access: Allowed connection to '%s' from %s (%s)\n",
120 : service_name, name, addr->addr));
121 : } else {
122 0 : DEBUG(0,("socket_check_access: Denied connection to '%s' from %s (%s)\n",
123 : service_name, name, addr->addr));
124 : }
125 :
126 0 : talloc_free(mem_ctx);
127 :
128 0 : return ret;
129 : }
|