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 netbios_name
= lp
.get("netbios name")
53 if not samba
.valid_netbios_name(netbios_name
):
54 logger
.error("netbios name %s is not a valid netbios name",
58 workgroup
= lp
.get("workgroup")
59 if not samba
.valid_netbios_name(workgroup
):
60 logger
.error("workgroup name %s is not a valid netbios name",
64 lockdir
= lp
.get("lockdir")
66 if not os
.path
.isdir(lockdir
):
67 logger
.error("lock directory %s does not exist", lockdir
)
70 piddir
= lp
.get("pid directory")
72 if not os
.path
.isdir(piddir
):
73 logger
.error("pid directory %s does not exist", piddir
)
76 winbind_separator
= lp
.get("winbind separator")
78 if len(winbind_separator
) != 1:
79 logger
.error("the 'winbind separator' parameter must be a single "
83 if winbind_separator
== '+':
84 logger
.error("'winbind separator = +' might cause problems with group "
91 def allow_access(deny_list
, allow_list
, cname
, caddr
):
92 raise NotImplementedError(allow_access
)
95 def do_share_checks(lp
, logger
):
97 for s
in lp
.services():
99 logger
.warning("You have some share names that are longer than 12 "
100 "characters. These may not be accessible to some older "
101 "clients. (Eg. Windows9x, WindowsMe, and not listed in "
102 "smbclient in Samba 3.0.)")
105 for s
in lp
.services():
106 deny_list
= lp
.get("hosts deny", s
)
107 allow_list
= lp
.get("hosts allow", s
)
109 for entry
in deny_list
:
110 if "*" in entry
or "?" in entry
:
111 logger
.error("Invalid character (* or ?) in hosts deny "
112 "list (%s) for service %s.", entry
, s
)
116 for entry
in allow_list
:
117 if "*" in entry
or "?" in entry
:
118 logger
.error("Invalid character (* or ?) in hosts allow "
119 "list (%s) for service %s.", entry
, s
)
123 def check_client_access(lp
, cname
, caddr
):
124 # this is totally ugly, a real `quick' hack
125 for s
in lp
.services():
126 if (allow_access(lp
.get("hosts deny"), lp
.get("hosts allow"), cname
,
128 allow_access(lp
.get("hosts deny", s
), lp
.get("hosts allow", s
),
130 logger
.info("Allow connection from %s (%s) to %s", cname
, caddr
, s
)
132 logger
.info("Deny connection from %s (%s) to %s", cname
, caddr
, s
)
135 if __name__
== '__main__':
136 parser
= optparse
.OptionParser("testparm [OPTION...] [host-name] [host-ip]")
137 parser
.add_option("--section-name", type="string", metavar
="SECTION",
138 help="Limit testparm to a named section")
139 parser
.add_option("--parameter-name", type="string", metavar
="PARAMETER",
140 help="Limit testparm to a named parameter")
141 parser
.add_option("--client-name", type="string", metavar
="HOSTNAME",
142 help="Client DNS name for 'hosts allow' checking "
143 "(should match reverse lookup)")
144 parser
.add_option("--client-ip", type="string", metavar
="IP",
145 help="Client IP address for 'hosts allow' checking")
146 parser
.add_option("--suppress-prompt", action
="store_true", default
=False,
147 help="Suppress prompt for enter")
148 parser
.add_option("-v", "--verbose", action
="store_true",
149 default
=False, help="Show default options too")
150 parser
.add_option_group(options
.VersionOptions(parser
))
151 # We need support for smb.conf macros before this will work again
152 parser
.add_option("--server", type="string",
153 help="Set %%L macro to servername")
154 # These are harder to do with the new code structure
155 parser
.add_option("--show-all-parameters", action
="store_true",
156 default
=False, help="Show the parameters, type, possible values")
158 sambaopts
= options
.SambaOptions(parser
)
159 parser
.add_option_group(sambaopts
)
161 opts
, args
= parser
.parse_args()
164 # if (show_all_parameters) {
165 # show_parameter_list()
178 if cname
is not None and caddr
is None:
179 print "Both a DNS name and an IP address are required for the host " \
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")
195 logger
.addHandler(logging
.StreamHandler(sys
.stdout
))
197 logger
.info("Loaded smb config files from %s", lp
.configfile
)
198 logger
.info("Loaded services file OK.")
200 valid
= do_global_checks(lp
, logger
)
201 valid
= valid
and do_share_checks(lp
, logger
)
202 if cname
is not None:
203 check_client_access(lp
, cname
, caddr
)
205 if opts
.section_name
is not None or opts
.parameter_name
is not None:
206 if opts
.parameter_name
is None:
207 lp
[opts
.section_name
].dump(sys
.stdout
, lp
.default_service
,
210 print lp
.get(opts
.parameter_name
, opts
.section_name
)
212 if not opts
.suppress_prompt
:
213 print "Press enter to see a dump of your service definitions\n"
215 lp
.dump(sys
.stdout
, opts
.verbose
)