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 131956 : bool socket_check_access(struct socket_context *sock, 76 : const char *service_name, 77 : const char **allow_list, const char **deny_list) 78 : { 79 3243 : bool ret; 80 131956 : const char *name=""; 81 3243 : struct socket_address *addr; 82 3243 : TALLOC_CTX *mem_ctx; 83 : 84 131956 : if ((!deny_list || *deny_list==0) && 85 0 : (!allow_list || *allow_list==0)) { 86 128713 : 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 : }