2 # vim: expandtab ft=python
4 # Unix SMB/CIFS implementation.
5 # Test validity of smb.conf
6 # Copyright (C) Karl Auer 1993, 1994-1998
8 # Extensively modified by Andrew Tridgell, 1995
9 # Converted to popt by Jelmer Vernooij (jelmer@nl.linux.org), 2002
10 # Updated for Samba4 by Andrew Bartlett <abartlet@samba.org> 2006
11 # Converted to Python by Jelmer Vernooij <jelmer@samba.org> 2010
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 3 of the License, or
16 # (at your option) any later version.
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 # Testbed for loadparm.c/params.c
28 # This module simply loads a specified configuration file and
29 # if successful, dumps it's contents to stdout. Note that the
30 # operation is performed with DEBUGLEVEL at 3.
32 # Useful for a quick 'syntax check' of a configuration file.
35 #/***********************************************
36 # Here we do a set of 'hard coded' checks for bad
37 # configuration settings.
38 #************************************************/
46 # Find right directory when running from source tree
47 sys.path.insert(0, "bin/python")
50 from samba import getopt as options
52 def do_global_checks(lp, logger):
55 lockdir = lp.get("lockdir")
57 if not os.path.isdir(lockdir):
58 logger.error("lock directory %s does not exist", lockdir)
61 piddir = lp.get("pid directory")
63 if os.path.isdir(piddir):
64 logger.error("pid directory %s does not exist", piddir)
67 winbind_separator = lp.get("winbind separator")
69 if len(winbind_separator) != 1:
70 logger.error("the 'winbind separator' parameter must be a single character.")
73 if winbind_separator == '+':
74 logger.error("'winbind separator = +' might cause problems with group membership.")
79 def allow_access(deny_list, allow_list, cname, caddr):
80 raise NotImplementedError(allow_access)
83 def do_share_checks(lp, cname, caddr, silent_mode, show_defaults, section_name,
84 parameter_name, logger):
87 for s in lp.services():
89 logger.warning("You have some share names that are longer than 12 characters. These may not be accessible to some older clients. (Eg. Windows9x, WindowsMe, and not listed in smbclient in Samba 3.0.)")
92 for s in lp.services():
93 deny_list = lp.get("hosts deny", s)
94 allow_list = lp.get("hosts allow", s)
96 for entry in deny_list:
97 if "*" in entry or "?" in entry:
98 logger.error("Invalid character (* or ?) in hosts deny list (%s) for service %s.", entry, s)
101 for entry in allow_list:
102 if "*" in entry or "?" in entry:
103 logger.error("Invalid character (* or ?) in hosts allow list (%s) for service %s.", entry, s)
105 if cname is not None:
107 print "Press enter to see a dump of your service definitions\n"
109 if section_name is not None or parameter_name is not None:
110 if parameter_name is None:
111 lp.dump_service(sys.stdout, section_name, show_defaults)
113 lp.dump_parameter(sys.stdout, section_name, parameter_name)
115 lp.dump(sys.stdout, show_defaults)
118 if cname is not None and caddr is not None:
119 # this is totally ugly, a real `quick' hack
120 for s in lp.services():
121 if (allow_access(lp.get("hosts deny"), lp.get("hosts allow"), cname, caddr) and
122 allow_access(lp.get("hosts deny", s), lp.get("hosts allow", s), cname, caddr)):
123 logger.info("Allow connection from %s (%s) to %s",
126 logger.info("Deny connection from %s (%s) to %s",
132 if __name__ == '__main__':
134 parameter_name = None
136 show_defaults = False
138 parser = optparse.OptionParser("testparm [OPTION...] [host-name] [host-ip]")
139 parser.add_option("--section-name", type="string", metavar="SECTION",
140 help="Limit testparm to a named section")
141 parser.add_option("--parameter-name", type="string", metavar="PARAMETER",
142 help="Limit testparm to a named parameter")
143 parser.add_option("--client-name", type="string", metavar="HOSTNAME",
144 help="Client DNS name for 'hosts allow' checking (should match reverse lookup)")
145 parser.add_option("--client-ip", type="string", metavar="IP",
146 help="Client IP address for 'hosts allow' checking")
147 parser.add_option("--suppress-prompt", action="store_true",
148 help="Suppress prompt for enter")
149 parser.add_option("--verbose", action="store_true",
150 help="Show default options too")
151 parser.add_option_group(options.VersionOptions(parser))
152 # We need support for smb.conf macros before this will work again
153 parser.add_option("--server", type="string",
154 help="Set %%L macro to servername")
155 # These are harder to do with the new code structure
156 parser.add_option("--show-all-parameters", action="store_true",
157 help="Show the parameters, type, possible values")
159 sambaopts = options.SambaOptions(parser)
160 parser.add_option_group(sambaopts)
162 opts, args = parser.parse_args()
165 # if (show_all_parameters) {
166 # show_parameter_list()
179 if cname is not None and caddr is None:
180 print "ERROR: For 'hosts allow' check you must specify both a DNS name and an IP address.\n"
183 # FIXME: We need support for smb.conf macros before this will work again
185 # if (new_local_machine) {
186 # set_local_machine_name(new_local_machine, True)
189 lp = sambaopts.get_loadparm()
191 # We need this to force the output
192 samba.set_debug_level(2)
194 logger = logging.getLogger("testparm")
196 print "Loaded smb config files from %s\n" % lp.configfile
198 logger.info("Loaded services file OK.")
200 do_global_checks(lp, logger)
201 do_share_checks(lp, cname, caddr, silent_mode, show_defaults,
202 section_name, parameter_name, logger)