2011-03-24 01:06:18 +03:00
# Unix SMB/CIFS implementation.
# Test validity of smb.conf
2011-10-13 01:10:14 +04:00
# Copyright (C) 2010-2011 Jelmer Vernooij <jelmer@samba.org>
2011-03-24 01:06:18 +03:00
#
2011-10-13 01:10:14 +04:00
# Based on the original in C:
# Copyright (C) Karl Auer 1993, 1994-1998
2011-03-24 01:06:18 +03:00
# Extensively modified by Andrew Tridgell, 1995
# Converted to popt by Jelmer Vernooij (jelmer@nl.linux.org), 2002
# Updated for Samba4 by Andrew Bartlett <abartlet@samba.org> 2006
#
2011-09-13 02:20:57 +04:00
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2011-03-24 01:06:18 +03:00
#
# Testbed for loadparm.c/params.c
#
# This module simply loads a specified configuration file and
# if successful, dumps it's contents to stdout. Note that the
# operation is performed with DEBUGLEVEL at 3.
#
# Useful for a quick 'syntax check' of a configuration file.
#
import os
import sys
import samba
import samba . getopt as options
from samba . netcmd import Command , CommandError , Option
class cmd_testparm ( Command ) :
2011-10-14 01:08:32 +04:00
""" Syntax check the configuration file. """
2011-03-24 01:06:18 +03:00
2011-10-14 01:27:22 +04:00
synopsis = " % prog [options] "
2011-03-24 01:06:18 +03:00
2012-02-06 19:33:38 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions
}
2011-03-24 01:06:18 +03:00
takes_options = [
Option ( " --section-name " , type = str ,
help = " Limit testparm to a named section " ) ,
Option ( " --parameter-name " , type = str ,
help = " Limit testparm to a named parameter " ) ,
Option ( " --client-name " , type = str ,
help = " Client DNS name for ' hosts allow ' checking "
" (should match reverse lookup) " ) ,
Option ( " --client-ip " , type = str ,
help = " Client IP address for ' hosts allow ' checking " ) ,
Option ( " --suppress-prompt " , action = " store_true " , default = False ,
help = " Suppress prompt for enter " ) ,
Option ( " -v " , " --verbose " , action = " store_true " ,
default = False , help = " Show default options too " ) ,
# We need support for smb.conf macros before this will work again
2012-11-09 12:07:38 +04:00
Option ( " --server " , type = str , help = " Set % L macro to servername " ) ,
2011-03-24 01:06:18 +03:00
# These are harder to do with the new code structure
Option ( " --show-all-parameters " , action = " store_true " , default = False ,
help = " Show the parameters, type, possible values " )
]
2011-10-13 01:10:14 +04:00
takes_args = [ ]
2012-09-16 16:18:39 +04:00
def run ( self , sambaopts , versionopts , section_name = None ,
parameter_name = None , client_ip = None , client_name = None ,
verbose = False , suppress_prompt = None , show_all_parameters = False ,
server = None ) :
2011-10-13 01:10:14 +04:00
if server :
raise NotImplementedError ( " --server not yet implemented " )
if show_all_parameters :
raise NotImplementedError ( " --show-all-parameters not yet implemented " )
if client_name is not None and client_ip is None :
raise CommandError ( " Both a DNS name and an IP address are "
2011-03-24 01:06:18 +03:00
" required for the host access check " )
2011-10-13 01:10:14 +04:00
lp = sambaopts . get_loadparm ( )
2011-03-24 01:06:18 +03:00
# We need this to force the output
samba . set_debug_level ( 2 )
2011-10-13 01:21:52 +04:00
logger = self . get_logger ( " testparm " )
2011-03-24 01:06:18 +03:00
logger . info ( " Loaded smb config files from %s " , lp . configfile )
logger . info ( " Loaded services file OK. " )
valid = self . do_global_checks ( lp , logger )
valid = valid and self . do_share_checks ( lp , logger )
2011-10-13 01:10:14 +04:00
if client_name is not None and client_ip is not None :
2011-10-13 01:11:14 +04:00
self . check_client_access ( lp , logger , client_name , client_ip )
2011-03-24 01:06:18 +03:00
else :
2011-10-13 01:10:14 +04:00
if section_name is not None or parameter_name is not None :
if parameter_name is None :
2012-09-16 16:18:39 +04:00
lp [ section_name ] . dump ( sys . stdout , lp . default_service ,
verbose )
2011-03-24 01:06:18 +03:00
else :
2011-10-13 02:36:44 +04:00
self . outf . write ( lp . get ( parameter_name , section_name ) + " \n " )
2011-03-24 01:06:18 +03:00
else :
2011-10-13 01:10:14 +04:00
if not suppress_prompt :
2011-10-13 02:36:44 +04:00
self . outf . write ( " Press enter to see a dump of your service definitions \n " )
2011-03-24 01:06:18 +03:00
sys . stdin . readline ( )
2011-10-13 01:10:14 +04:00
lp . dump ( sys . stdout , verbose )
2011-03-24 01:06:18 +03:00
if valid :
return
else :
raise CommandError ( " Invalid smb.conf " )
def do_global_checks ( self , lp , logger ) :
valid = True
netbios_name = lp . get ( " netbios name " )
if not samba . valid_netbios_name ( netbios_name ) :
logger . error ( " netbios name %s is not a valid netbios name " ,
netbios_name )
valid = False
workgroup = lp . get ( " workgroup " )
if not samba . valid_netbios_name ( workgroup ) :
logger . error ( " workgroup name %s is not a valid netbios name " ,
workgroup )
valid = False
lockdir = lp . get ( " lockdir " )
if not os . path . isdir ( lockdir ) :
logger . error ( " lock directory %s does not exist " , lockdir )
valid = False
piddir = lp . get ( " pid directory " )
if not os . path . isdir ( piddir ) :
logger . error ( " pid directory %s does not exist " , piddir )
valid = False
winbind_separator = lp . get ( " winbind separator " )
if len ( winbind_separator ) != 1 :
logger . error ( " the ' winbind separator ' parameter must be a single "
" character. " )
valid = False
if winbind_separator == ' + ' :
2012-09-16 16:18:39 +04:00
logger . error (
" ' winbind separator = + ' might cause problems with group "
" membership. " )
2011-03-24 01:06:18 +03:00
valid = False
return valid
def allow_access ( self , deny_list , allow_list , cname , caddr ) :
raise NotImplementedError ( self . allow_access )
def do_share_checks ( self , lp , logger ) :
valid = True
for s in lp . services ( ) :
if len ( s ) > 12 :
2012-09-16 16:18:39 +04:00
logger . warning (
" You have some share names that are longer than 12 "
2011-03-24 01:06:18 +03:00
" characters. These may not be accessible to some older "
" clients. (Eg. Windows9x, WindowsMe, and not listed in "
" smbclient in Samba 3.0.) " )
break
for s in lp . services ( ) :
deny_list = lp . get ( " hosts deny " , s )
allow_list = lp . get ( " hosts allow " , s )
if deny_list :
for entry in deny_list :
if " * " in entry or " ? " in entry :
logger . error ( " Invalid character (* or ?) in hosts deny "
" list ( %s ) for service %s . " , entry , s )
valid = False
if allow_list :
for entry in allow_list :
if " * " in entry or " ? " in entry :
logger . error ( " Invalid character (* or ?) in hosts allow "
" list ( %s ) for service %s . " , entry , s )
valid = False
return valid
2011-10-13 01:11:14 +04:00
def check_client_access ( self , lp , logger , cname , caddr ) :
2011-03-24 01:06:18 +03:00
# this is totally ugly, a real `quick' hack
for s in lp . services ( ) :
if ( self . allow_access ( lp . get ( " hosts deny " ) , lp . get ( " hosts allow " ) , cname ,
caddr ) and
self . allow_access ( lp . get ( " hosts deny " , s ) , lp . get ( " hosts allow " , s ) ,
cname , caddr ) ) :
logger . info ( " Allow connection from %s ( %s ) to %s " , cname , caddr , s )
else :
logger . info ( " Deny connection from %s ( %s ) to %s " , cname , caddr , s )
## FIXME: We need support for smb.conf macros before this will work again
##
## if (new_local_machine) {
## set_local_machine_name(new_local_machine, True)
## }
#