uwrap: Add library constructor and move pthread_atfork inside.
[Samba.git] / source3 / utils / testparm.c
blob50518c2f12f4bc3709c17430ceb24fcccd81c055
1 /*
2 Unix SMB/CIFS implementation.
3 Test validity of smb.conf
4 Copyright (C) Karl Auer 1993, 1994-1998
6 Extensively modified by Andrew Tridgell, 1995
7 Converted to popt by Jelmer Vernooij (jelmer@nl.linux.org), 2002
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * Testbed for loadparm.c/params.c
26 * This module simply loads a specified configuration file and
27 * if successful, dumps it's contents to stdout. Note that the
28 * operation is performed with DEBUGLEVEL at 3.
30 * Useful for a quick 'syntax check' of a configuration file.
34 #include "includes.h"
35 #include "system/filesys.h"
36 #include "popt_common.h"
37 #include "lib/param/loadparm.h"
39 /*******************************************************************
40 Check if a directory exists.
41 ********************************************************************/
43 static bool directory_exist_stat(const char *dname,SMB_STRUCT_STAT *st)
45 SMB_STRUCT_STAT st2;
46 bool ret;
48 if (!st)
49 st = &st2;
51 if (sys_stat(dname, st, false) != 0)
52 return(False);
54 ret = S_ISDIR(st->st_ex_mode);
55 if(!ret)
56 errno = ENOTDIR;
57 return ret;
60 /***********************************************
61 Here we do a set of 'hard coded' checks for bad
62 configuration settings.
63 ************************************************/
65 static int do_global_checks(void)
67 int ret = 0;
68 SMB_STRUCT_STAT st;
69 const char *socket_options;
71 if (lp_security() >= SEC_DOMAIN && !lp_encrypt_passwords()) {
72 fprintf(stderr, "ERROR: in 'security=domain' mode the "
73 "'encrypt passwords' parameter must always be "
74 "set to 'true'.\n\n");
75 ret = 1;
78 if (lp_we_are_a_wins_server() && lp_wins_server_list()) {
79 fprintf(stderr, "ERROR: both 'wins support = true' and "
80 "'wins server = <server list>' cannot be set in "
81 "the smb.conf file. nmbd will abort with this "
82 "setting.\n\n");
83 ret = 1;
86 if (strequal(lp_workgroup(), lp_netbios_name())) {
87 fprintf(stderr, "WARNING: 'workgroup' and 'netbios name' "
88 "must differ.\n\n");
91 if (!directory_exist_stat(lp_lock_directory(), &st)) {
92 fprintf(stderr, "ERROR: lock directory %s does not exist\n\n",
93 lp_lock_directory());
94 ret = 1;
95 } else if ((st.st_ex_mode & 0777) != 0755) {
96 fprintf(stderr, "WARNING: lock directory %s should have "
97 "permissions 0755 for browsing to work\n\n",
98 lp_lock_directory());
101 if (!directory_exist_stat(lp_state_directory(), &st)) {
102 fprintf(stderr, "ERROR: state directory %s does not exist\n\n",
103 lp_state_directory());
104 ret = 1;
105 } else if ((st.st_ex_mode & 0777) != 0755) {
106 fprintf(stderr, "WARNING: state directory %s should have "
107 "permissions 0755 for browsing to work\n\n",
108 lp_state_directory());
111 if (!directory_exist_stat(lp_cache_directory(), &st)) {
112 fprintf(stderr, "ERROR: cache directory %s does not exist\n\n",
113 lp_cache_directory());
114 ret = 1;
115 } else if ((st.st_ex_mode & 0777) != 0755) {
116 fprintf(stderr, "WARNING: cache directory %s should have "
117 "permissions 0755 for browsing to work\n\n",
118 lp_cache_directory());
121 if (!directory_exist_stat(lp_pid_directory(), &st)) {
122 fprintf(stderr, "ERROR: pid directory %s does not exist\n\n",
123 lp_pid_directory());
124 ret = 1;
127 if (lp_passdb_expand_explicit()) {
128 fprintf(stderr, "WARNING: passdb expand explicit = yes is "
129 "deprecated\n\n");
133 * Socket options.
135 socket_options = lp_socket_options();
136 if (socket_options != NULL &&
137 (strstr(socket_options, "SO_SNDBUF") ||
138 strstr(socket_options, "SO_RCVBUF") ||
139 strstr(socket_options, "SO_SNDLOWAT") ||
140 strstr(socket_options, "SO_RCVLOWAT")))
142 fprintf(stderr,
143 "WARNING: socket options = %s\n"
144 "This warning is printed because you set one of the\n"
145 "following options: SO_SNDBUF, SO_RCVBUF, SO_SNDLOWAT,\n"
146 "SO_RCVLOWAT\n"
147 "Modern server operating systems are tuned for\n"
148 "high network performance in the majority of situations;\n"
149 "when you set 'socket options' you are overriding those\n"
150 "settings.\n"
151 "Linux in particular has an auto-tuning mechanism for\n"
152 "buffer sizes (SO_SNDBUF, SO_RCVBUF) that will be\n"
153 "disabled if you specify a socket buffer size. This can\n"
154 "potentially cripple your TCP/IP stack.\n\n"
155 "Getting the 'socket options' correct can make a big\n"
156 "difference to your performance, but getting them wrong\n"
157 "can degrade it by just as much. As with any other low\n"
158 "level setting, if you must make changes to it, make\n "
159 "small changes and test the effect before making any\n"
160 "large changes.\n\n",
161 socket_options);
165 * Password server sanity checks.
168 if((lp_security() >= SEC_DOMAIN) && !*lp_password_server()) {
169 const char *sec_setting;
170 if(lp_security() == SEC_DOMAIN)
171 sec_setting = "domain";
172 else if(lp_security() == SEC_ADS)
173 sec_setting = "ads";
174 else
175 sec_setting = "";
177 fprintf(stderr, "ERROR: The setting 'security=%s' requires the "
178 "'password server' parameter be set to the "
179 "default value * or a valid password server.\n\n",
180 sec_setting );
181 ret = 1;
184 if((lp_security() >= SEC_DOMAIN) && (strcmp(lp_password_server(), "*") != 0)) {
185 const char *sec_setting;
186 if(lp_security() == SEC_DOMAIN)
187 sec_setting = "domain";
188 else if(lp_security() == SEC_ADS)
189 sec_setting = "ads";
190 else
191 sec_setting = "";
193 fprintf(stderr, "WARNING: The setting 'security=%s' should NOT "
194 "be combined with the 'password server' "
195 "parameter.\n"
196 "(by default Samba will discover the correct DC "
197 "to contact automatically).\n\n",
198 sec_setting );
202 * Password chat sanity checks.
205 if(lp_security() == SEC_USER && lp_unix_password_sync()) {
208 * Check that we have a valid lp_passwd_program() if not using pam.
211 #ifdef WITH_PAM
212 if (!lp_pam_password_change()) {
213 #endif
215 if((lp_passwd_program(talloc_tos()) == NULL) ||
216 (strlen(lp_passwd_program(talloc_tos())) == 0))
218 fprintf(stderr,
219 "ERROR: the 'unix password sync' "
220 "parameter is set and there is no valid "
221 "'passwd program' parameter.\n\n");
222 ret = 1;
223 } else {
224 const char *passwd_prog;
225 char *truncated_prog = NULL;
226 const char *p;
228 passwd_prog = lp_passwd_program(talloc_tos());
229 p = passwd_prog;
230 next_token_talloc(talloc_tos(),
232 &truncated_prog, NULL);
233 if (truncated_prog && access(truncated_prog, F_OK) == -1) {
234 fprintf(stderr,
235 "ERROR: the 'unix password sync' "
236 "parameter is set and the "
237 "'passwd program' (%s) cannot be "
238 "executed (error was %s).\n\n",
239 truncated_prog,
240 strerror(errno));
241 ret = 1;
245 #ifdef WITH_PAM
247 #endif
249 if(lp_passwd_chat(talloc_tos()) == NULL) {
250 fprintf(stderr,
251 "ERROR: the 'unix password sync' parameter is "
252 "set and there is no valid 'passwd chat' "
253 "parameter.\n\n");
254 ret = 1;
257 if ((lp_passwd_program(talloc_tos()) != NULL) &&
258 (strlen(lp_passwd_program(talloc_tos())) > 0))
260 /* check if there's a %u parameter present */
261 if(strstr_m(lp_passwd_program(talloc_tos()), "%u") == NULL) {
262 fprintf(stderr,
263 "ERROR: the 'passwd program' (%s) "
264 "requires a '%%u' parameter.\n\n",
265 lp_passwd_program(talloc_tos()));
266 ret = 1;
271 * Check that we have a valid script and that it hasn't
272 * been written to expect the old password.
275 if(lp_encrypt_passwords()) {
276 if(strstr_m( lp_passwd_chat(talloc_tos()), "%o")!=NULL) {
277 fprintf(stderr,
278 "ERROR: the 'passwd chat' script [%s] "
279 "expects to use the old plaintext "
280 "password via the %%o substitution. With "
281 "encrypted passwords this is not "
282 "possible.\n\n",
283 lp_passwd_chat(talloc_tos()) );
284 ret = 1;
289 if (strlen(lp_winbind_separator()) != 1) {
290 fprintf(stderr, "ERROR: the 'winbind separator' parameter must "
291 "be a single character.\n\n");
292 ret = 1;
295 if (*lp_winbind_separator() == '+') {
296 fprintf(stderr, "'winbind separator = +' might cause problems "
297 "with group membership.\n\n");
300 if (lp_algorithmic_rid_base() < BASE_RID) {
301 /* Try to prevent admin foot-shooting, we can't put algorithmic
302 rids below 1000, that's the 'well known RIDs' on NT */
303 fprintf(stderr, "'algorithmic rid base' must be equal to or "
304 "above %lu\n\n", BASE_RID);
307 if (lp_algorithmic_rid_base() & 1) {
308 fprintf(stderr, "'algorithmic rid base' must be even.\n\n");
311 #ifndef HAVE_DLOPEN
312 if (lp_preload_modules()) {
313 fprintf(stderr, "WARNING: 'preload modules = ' set while loading "
314 "plugins not supported.\n\n");
316 #endif
318 if (!lp_passdb_backend()) {
319 fprintf(stderr, "ERROR: passdb backend must have a value or be "
320 "left out\n\n");
323 if (lp_os_level() > 255) {
324 fprintf(stderr, "WARNING: Maximum value for 'os level' is "
325 "255!\n\n");
328 if (strequal(lp_dos_charset(), "UTF8") || strequal(lp_dos_charset(), "UTF-8")) {
329 fprintf(stderr, "ERROR: 'dos charset' must not be UTF8\n\n");
330 ret = 1;
333 return ret;
337 * per-share logic tests
339 static void do_per_share_checks(int s)
341 const char **deny_list = lp_hosts_deny(s);
342 const char **allow_list = lp_hosts_allow(s);
343 int i;
345 if(deny_list) {
346 for (i=0; deny_list[i]; i++) {
347 char *hasstar = strchr_m(deny_list[i], '*');
348 char *hasquery = strchr_m(deny_list[i], '?');
349 if(hasstar || hasquery) {
350 fprintf(stderr,
351 "Invalid character %c in hosts deny list "
352 "(%s) for service %s.\n\n",
353 hasstar ? *hasstar : *hasquery,
354 deny_list[i],
355 lp_servicename(talloc_tos(), s));
360 if(allow_list) {
361 for (i=0; allow_list[i]; i++) {
362 char *hasstar = strchr_m(allow_list[i], '*');
363 char *hasquery = strchr_m(allow_list[i], '?');
364 if(hasstar || hasquery) {
365 fprintf(stderr,
366 "Invalid character %c in hosts allow "
367 "list (%s) for service %s.\n\n",
368 hasstar ? *hasstar : *hasquery,
369 allow_list[i],
370 lp_servicename(talloc_tos(), s));
375 if(lp_level2_oplocks(s) && !lp_oplocks(s)) {
376 fprintf(stderr, "Invalid combination of parameters for service "
377 "%s. Level II oplocks can only be set if oplocks "
378 "are also set.\n\n",
379 lp_servicename(talloc_tos(), s));
382 if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
383 && !(lp_create_mask(s) & S_IXOTH))
385 fprintf(stderr,
386 "Invalid combination of parameters for service %s. Map "
387 "hidden can only work if create mask includes octal "
388 "01 (S_IXOTH).\n\n",
389 lp_servicename(talloc_tos(), s));
391 if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
392 && (lp_force_create_mode(s) & S_IXOTH))
394 fprintf(stderr,
395 "Invalid combination of parameters for service "
396 "%s. Map hidden can only work if force create mode "
397 "excludes octal 01 (S_IXOTH).\n\n",
398 lp_servicename(talloc_tos(), s));
400 if (!lp_store_dos_attributes(s) && lp_map_system(s)
401 && !(lp_create_mask(s) & S_IXGRP))
403 fprintf(stderr,
404 "Invalid combination of parameters for service "
405 "%s. Map system can only work if create mask includes "
406 "octal 010 (S_IXGRP).\n\n",
407 lp_servicename(talloc_tos(), s));
409 if (!lp_store_dos_attributes(s) && lp_map_system(s)
410 && (lp_force_create_mode(s) & S_IXGRP))
412 fprintf(stderr,
413 "Invalid combination of parameters for service "
414 "%s. Map system can only work if force create mode "
415 "excludes octal 010 (S_IXGRP).\n\n",
416 lp_servicename(talloc_tos(), s));
418 if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(talloc_tos(), s)) != '\0') {
419 fprintf(stderr,
420 "Warning: Service %s defines a print command, but "
421 "parameter is ignored when using CUPS libraries.\n\n",
422 lp_servicename(talloc_tos(), s));
426 int main(int argc, const char *argv[])
428 const char *config_file = get_dyn_CONFIGFILE();
429 int s;
430 static int silent_mode = False;
431 static int show_all_parameters = False;
432 int ret = 0;
433 poptContext pc;
434 static char *parameter_name = NULL;
435 static const char *section_name = NULL;
436 const char *cname;
437 const char *caddr;
438 static int show_defaults;
439 static int skip_logic_checks = 0;
441 struct poptOption long_options[] = {
442 POPT_AUTOHELP
443 {"suppress-prompt", 's', POPT_ARG_VAL, &silent_mode, 1, "Suppress prompt for enter"},
444 {"verbose", 'v', POPT_ARG_NONE, &show_defaults, 1, "Show default options too"},
445 {"skip-logic-checks", 'l', POPT_ARG_NONE, &skip_logic_checks, 1, "Skip the global checks"},
446 {"show-all-parameters", '\0', POPT_ARG_VAL, &show_all_parameters, True, "Show the parameters, type, possible values" },
447 {"parameter-name", '\0', POPT_ARG_STRING, &parameter_name, 0, "Limit testparm to a named parameter" },
448 {"section-name", '\0', POPT_ARG_STRING, &section_name, 0, "Limit testparm to a named section" },
449 POPT_COMMON_VERSION
450 POPT_COMMON_DEBUGLEVEL
451 POPT_COMMON_OPTION
452 POPT_TABLEEND
455 TALLOC_CTX *frame = talloc_stackframe();
457 load_case_tables();
459 * Set the default debug level to 2.
460 * Allow it to be overridden by the command line,
461 * not by smb.conf.
463 lp_set_cmdline("log level", "2");
465 pc = poptGetContext(NULL, argc, argv, long_options,
466 POPT_CONTEXT_KEEP_FIRST);
467 poptSetOtherOptionHelp(pc, "[OPTION...] <config-file> [host-name] [host-ip]");
469 while(poptGetNextOpt(pc) != -1);
471 if (show_all_parameters) {
472 show_parameter_list();
473 exit(0);
476 setup_logging(poptGetArg(pc), DEBUG_STDERR);
478 if (poptPeekArg(pc))
479 config_file = poptGetArg(pc);
481 cname = poptGetArg(pc);
482 caddr = poptGetArg(pc);
484 poptFreeContext(pc);
486 if ( cname && ! caddr ) {
487 printf ( "ERROR: You must specify both a machine name and an IP address.\n" );
488 ret = 1;
489 goto done;
492 fprintf(stderr,"Load smb config files from %s\n",config_file);
494 if (!lp_load_with_registry_shares(config_file,False,True,False,True)) {
495 fprintf(stderr,"Error loading services.\n");
496 ret = 1;
497 goto done;
500 fprintf(stderr,"Loaded services file OK.\n");
502 if (skip_logic_checks == 0) {
503 ret = do_global_checks();
506 for (s=0;s<1000;s++) {
507 if (VALID_SNUM(s))
508 if (strlen(lp_servicename(talloc_tos(), s)) > 12) {
509 fprintf(stderr, "WARNING: You have some share names that are longer than 12 characters.\n" );
510 fprintf(stderr, "These may not be accessible to some older clients.\n" );
511 fprintf(stderr, "(Eg. Windows9x, WindowsMe, and smbclient prior to Samba 3.0.)\n" );
512 break;
516 for (s=0;s<1000;s++) {
517 if (VALID_SNUM(s) && (skip_logic_checks == 0)) {
518 do_per_share_checks(s);
523 if (!section_name && !parameter_name) {
524 fprintf(stderr,
525 "Server role: %s\n\n",
526 server_role_str(lp_server_role()));
529 if (!cname) {
530 if (!silent_mode) {
531 fprintf(stderr,"Press enter to see a dump of your service definitions\n");
532 fflush(stdout);
533 getc(stdin);
535 if (parameter_name || section_name) {
536 bool isGlobal = False;
537 s = GLOBAL_SECTION_SNUM;
539 if (!section_name) {
540 section_name = GLOBAL_NAME;
541 isGlobal = True;
542 } else if ((isGlobal=!strwicmp(section_name, GLOBAL_NAME)) == 0 &&
543 (s=lp_servicenumber(section_name)) == -1) {
544 fprintf(stderr,"Unknown section %s\n",
545 section_name);
546 ret = 1;
547 goto done;
549 if (parameter_name) {
550 if (!dump_a_parameter( s, parameter_name, stdout, isGlobal)) {
551 fprintf(stderr,"Parameter %s unknown for section %s\n",
552 parameter_name, section_name);
553 ret = 1;
554 goto done;
556 } else {
557 if (isGlobal == True)
558 lp_dump(stdout, show_defaults, 0);
559 else
560 lp_dump_one(stdout, show_defaults, s);
562 goto done;
565 lp_dump(stdout, show_defaults, lp_numservices());
568 if(cname && caddr){
569 /* this is totally ugly, a real `quick' hack */
570 for (s=0;s<1000;s++) {
571 if (VALID_SNUM(s)) {
572 if (allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1), cname, caddr)
573 && allow_access(lp_hosts_deny(s), lp_hosts_allow(s), cname, caddr)) {
574 fprintf(stderr,"Allow connection from %s (%s) to %s\n",
575 cname,caddr,lp_servicename(talloc_tos(), s));
576 } else {
577 fprintf(stderr,"Deny connection from %s (%s) to %s\n",
578 cname,caddr,lp_servicename(talloc_tos(), s));
584 done:
585 gfree_loadparm();
586 TALLOC_FREE(frame);
587 return ret;