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.
40 # Find right directory when running from source tree
41 sys.path.insert(0, "bin/python")
44 from samba import getopt as options
46 # Here we do a set of 'hard coded' checks for bad
47 # configuration settings.
49 def do_global_checks(lp, logger):
52 lockdir = lp.get("lockdir")
54 if not os.path.isdir(lockdir):
55 logger.error("lock directory %s does not exist", lockdir)
58 piddir = lp.get("pid directory")
60 if not os.path.isdir(piddir):
61 logger.error("pid directory %s does not exist", piddir)
64 winbind_separator = lp.get("winbind separator")
66 if len(winbind_separator) != 1:
67 logger.error("the 'winbind separator' parameter must be a single character.")
70 if winbind_separator == '+':
71 logger.error("'winbind separator = +' might cause problems with group membership.")
77 def allow_access(deny_list, allow_list, cname, caddr):
78 raise NotImplementedError(allow_access)
81 def do_share_checks(lp, logger):
83 for s in lp.services():
85 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.)")
88 for s in lp.services():
89 deny_list = lp.get("hosts deny", s)
90 allow_list = lp.get("hosts allow", s)
92 for entry in deny_list:
93 if "*" in entry or "?" in entry:
94 logger.error("Invalid character (* or ?) in hosts deny list (%s) for service %s.", entry, s)
98 for entry in allow_list:
99 if "*" in entry or "?" in entry:
100 logger.error("Invalid character (* or ?) in hosts allow list (%s) for service %s.", entry, s)
104 def check_client_access(lp, cname, caddr):
105 # this is totally ugly, a real `quick' hack
106 for s in lp.services():
107 if (allow_access(lp.get("hosts deny"), lp.get("hosts allow"), cname, caddr) and
108 allow_access(lp.get("hosts deny", s), lp.get("hosts allow", s), cname, caddr)):
109 logger.info("Allow connection from %s (%s) to %s",
112 logger.info("Deny connection from %s (%s) to %s",
116 if __name__ == '__main__':
117 parser = optparse.OptionParser("testparm [OPTION...] [host-name] [host-ip]")
118 parser.add_option("--section-name", type="string", metavar="SECTION",
119 help="Limit testparm to a named section")
120 parser.add_option("--parameter-name", type="string", metavar="PARAMETER",
121 help="Limit testparm to a named parameter")
122 parser.add_option("--client-name", type="string", metavar="HOSTNAME",
123 help="Client DNS name for 'hosts allow' checking (should match reverse lookup)")
124 parser.add_option("--client-ip", type="string", metavar="IP",
125 help="Client IP address for 'hosts allow' checking")
126 parser.add_option("--suppress-prompt", action="store_true", default=False,
127 help="Suppress prompt for enter")
128 parser.add_option("-v", "--verbose", action="store_true",
129 default=False, help="Show default options too")
130 parser.add_option_group(options.VersionOptions(parser))
131 # We need support for smb.conf macros before this will work again
132 parser.add_option("--server", type="string",
133 help="Set %%L macro to servername")
134 # These are harder to do with the new code structure
135 parser.add_option("--show-all-parameters", action="store_true",
136 default=False, help="Show the parameters, type, possible values")
138 sambaopts = options.SambaOptions(parser)
139 parser.add_option_group(sambaopts)
141 opts, args = parser.parse_args()
144 # if (show_all_parameters) {
145 # show_parameter_list()
158 if cname is not None and caddr is None:
159 print "ERROR: For 'hosts allow' check you must specify both a DNS name and an IP address.\n"
162 # FIXME: We need support for smb.conf macros before this will work again
164 # if (new_local_machine) {
165 # set_local_machine_name(new_local_machine, True)
168 lp = sambaopts.get_loadparm()
170 # We need this to force the output
171 samba.set_debug_level(2)
173 logger = logging.getLogger("testparm")
174 logger.addHandler(logging.StreamHandler(sys.stdout))
176 logger.info("Loaded smb config files from %s", lp.configfile)
177 logger.info("Loaded services file OK.")
179 valid = do_global_checks(lp, logger)
180 valid = valid and do_share_checks(lp, logger)
181 if cname is not None:
182 check_client_access(lp, cname, caddr)
184 if opts.section_name is not None or opts.parameter_name is not None:
185 if opts.parameter_name is None:
186 lp[opts.section_name].dump(sys.stdout, lp.default_service, opts.verbose)
188 print lp.get(opts.parameter_name, opts.section_name)
190 if not opts.suppress_prompt:
191 print "Press enter to see a dump of your service definitions\n"
193 lp.dump(sys.stdout, opts.verbose)