source: vendor/current/source3/utils/testparm.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 16.4 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Test validity of smb.conf
4 Copyright (C) Karl Auer 1993, 1994-1998
5
6 Extensively modified by Andrew Tridgell, 1995
7 Converted to popt by Jelmer Vernooij (jelmer@nl.linux.org), 2002
8
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.
13
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.
18
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/>.
21*/
22
23/*
24 * Testbed for loadparm.c/params.c
25 *
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.
29 *
30 * Useful for a quick 'syntax check' of a configuration file.
31 *
32 */
33
34#include "includes.h"
35#include "system/filesys.h"
36#include "popt_common.h"
37#include "lib/param/loadparm.h"
38
39/*******************************************************************
40 Check if a directory exists.
41********************************************************************/
42
43static bool directory_exist_stat(const char *dname,SMB_STRUCT_STAT *st)
44{
45 SMB_STRUCT_STAT st2;
46 bool ret;
47
48 if (!st)
49 st = &st2;
50
51 if (sys_stat(dname, st, false) != 0)
52 return(False);
53
54 ret = S_ISDIR(st->st_ex_mode);
55 if(!ret)
56 errno = ENOTDIR;
57 return ret;
58}
59
60/***********************************************
61 Here we do a set of 'hard coded' checks for bad
62 configuration settings.
63************************************************/
64
65static int do_global_checks(void)
66{
67 int ret = 0;
68 SMB_STRUCT_STAT st;
69 const char *socket_options;
70
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;
76 }
77
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;
84 }
85
86 if (strequal(lp_workgroup(), lp_netbios_name())) {
87 fprintf(stderr, "WARNING: 'workgroup' and 'netbios name' "
88 "must differ.\n\n");
89 }
90
91 if (strlen(lp_netbios_name()) > 15) {
92 fprintf(stderr, "WARNING: The 'netbios name' is too long "
93 "(max. 15 chars).\n\n");
94 }
95
96 if (!directory_exist_stat(lp_lock_directory(), &st)) {
97 fprintf(stderr, "ERROR: lock directory %s does not exist\n\n",
98 lp_lock_directory());
99 ret = 1;
100 } else if ((st.st_ex_mode & 0777) != 0755) {
101 fprintf(stderr, "WARNING: lock directory %s should have "
102 "permissions 0755 for browsing to work\n\n",
103 lp_lock_directory());
104 }
105
106 if (!directory_exist_stat(lp_state_directory(), &st)) {
107 fprintf(stderr, "ERROR: state directory %s does not exist\n\n",
108 lp_state_directory());
109 ret = 1;
110 } else if ((st.st_ex_mode & 0777) != 0755) {
111 fprintf(stderr, "WARNING: state directory %s should have "
112 "permissions 0755 for browsing to work\n\n",
113 lp_state_directory());
114 }
115
116 if (!directory_exist_stat(lp_cache_directory(), &st)) {
117 fprintf(stderr, "ERROR: cache directory %s does not exist\n\n",
118 lp_cache_directory());
119 ret = 1;
120 } else if ((st.st_ex_mode & 0777) != 0755) {
121 fprintf(stderr, "WARNING: cache directory %s should have "
122 "permissions 0755 for browsing to work\n\n",
123 lp_cache_directory());
124 }
125
126 if (!directory_exist_stat(lp_pid_directory(), &st)) {
127 fprintf(stderr, "ERROR: pid directory %s does not exist\n\n",
128 lp_pid_directory());
129 ret = 1;
130 }
131
132 if (lp_passdb_expand_explicit()) {
133 fprintf(stderr, "WARNING: passdb expand explicit = yes is "
134 "deprecated\n\n");
135 }
136
137 /*
138 * Socket options.
139 */
140 socket_options = lp_socket_options();
141 if (socket_options != NULL &&
142 (strstr(socket_options, "SO_SNDBUF") ||
143 strstr(socket_options, "SO_RCVBUF") ||
144 strstr(socket_options, "SO_SNDLOWAT") ||
145 strstr(socket_options, "SO_RCVLOWAT")))
146 {
147 fprintf(stderr,
148 "WARNING: socket options = %s\n"
149 "This warning is printed because you set one of the\n"
150 "following options: SO_SNDBUF, SO_RCVBUF, SO_SNDLOWAT,\n"
151 "SO_RCVLOWAT\n"
152 "Modern server operating systems are tuned for\n"
153 "high network performance in the majority of situations;\n"
154 "when you set 'socket options' you are overriding those\n"
155 "settings.\n"
156 "Linux in particular has an auto-tuning mechanism for\n"
157 "buffer sizes (SO_SNDBUF, SO_RCVBUF) that will be\n"
158 "disabled if you specify a socket buffer size. This can\n"
159 "potentially cripple your TCP/IP stack.\n\n"
160 "Getting the 'socket options' correct can make a big\n"
161 "difference to your performance, but getting them wrong\n"
162 "can degrade it by just as much. As with any other low\n"
163 "level setting, if you must make changes to it, make\n "
164 "small changes and test the effect before making any\n"
165 "large changes.\n\n",
166 socket_options);
167 }
168
169 /*
170 * Password server sanity checks.
171 */
172
173 if((lp_security() >= SEC_DOMAIN) && !*lp_password_server()) {
174 const char *sec_setting;
175 if(lp_security() == SEC_DOMAIN)
176 sec_setting = "domain";
177 else if(lp_security() == SEC_ADS)
178 sec_setting = "ads";
179 else
180 sec_setting = "";
181
182 fprintf(stderr, "ERROR: The setting 'security=%s' requires the "
183 "'password server' parameter be set to the "
184 "default value * or a valid password server.\n\n",
185 sec_setting );
186 ret = 1;
187 }
188
189 if((lp_security() >= SEC_DOMAIN) && (strcmp(lp_password_server(), "*") != 0)) {
190 const char *sec_setting;
191 if(lp_security() == SEC_DOMAIN)
192 sec_setting = "domain";
193 else if(lp_security() == SEC_ADS)
194 sec_setting = "ads";
195 else
196 sec_setting = "";
197
198 fprintf(stderr, "WARNING: The setting 'security=%s' should NOT "
199 "be combined with the 'password server' "
200 "parameter.\n"
201 "(by default Samba will discover the correct DC "
202 "to contact automatically).\n\n",
203 sec_setting );
204 }
205
206 /*
207 * Password chat sanity checks.
208 */
209
210 if(lp_security() == SEC_USER && lp_unix_password_sync()) {
211
212 /*
213 * Check that we have a valid lp_passwd_program() if not using pam.
214 */
215
216#ifdef WITH_PAM
217 if (!lp_pam_password_change()) {
218#endif
219
220 if((lp_passwd_program(talloc_tos()) == NULL) ||
221 (strlen(lp_passwd_program(talloc_tos())) == 0))
222 {
223 fprintf(stderr,
224 "ERROR: the 'unix password sync' "
225 "parameter is set and there is no valid "
226 "'passwd program' parameter.\n\n");
227 ret = 1;
228 } else {
229 const char *passwd_prog;
230 char *truncated_prog = NULL;
231 const char *p;
232
233 passwd_prog = lp_passwd_program(talloc_tos());
234 p = passwd_prog;
235 next_token_talloc(talloc_tos(),
236 &p,
237 &truncated_prog, NULL);
238 if (truncated_prog && access(truncated_prog, F_OK) == -1) {
239 fprintf(stderr,
240 "ERROR: the 'unix password sync' "
241 "parameter is set and the "
242 "'passwd program' (%s) cannot be "
243 "executed (error was %s).\n\n",
244 truncated_prog,
245 strerror(errno));
246 ret = 1;
247 }
248 }
249
250#ifdef WITH_PAM
251 }
252#endif
253
254 if(lp_passwd_chat(talloc_tos()) == NULL) {
255 fprintf(stderr,
256 "ERROR: the 'unix password sync' parameter is "
257 "set and there is no valid 'passwd chat' "
258 "parameter.\n\n");
259 ret = 1;
260 }
261
262 if ((lp_passwd_program(talloc_tos()) != NULL) &&
263 (strlen(lp_passwd_program(talloc_tos())) > 0))
264 {
265 /* check if there's a %u parameter present */
266 if(strstr_m(lp_passwd_program(talloc_tos()), "%u") == NULL) {
267 fprintf(stderr,
268 "ERROR: the 'passwd program' (%s) "
269 "requires a '%%u' parameter.\n\n",
270 lp_passwd_program(talloc_tos()));
271 ret = 1;
272 }
273 }
274
275 /*
276 * Check that we have a valid script and that it hasn't
277 * been written to expect the old password.
278 */
279
280 if(lp_encrypt_passwords()) {
281 if(strstr_m( lp_passwd_chat(talloc_tos()), "%o")!=NULL) {
282 fprintf(stderr,
283 "ERROR: the 'passwd chat' script [%s] "
284 "expects to use the old plaintext "
285 "password via the %%o substitution. With "
286 "encrypted passwords this is not "
287 "possible.\n\n",
288 lp_passwd_chat(talloc_tos()) );
289 ret = 1;
290 }
291 }
292 }
293
294 if (strlen(lp_winbind_separator()) != 1) {
295 fprintf(stderr, "ERROR: the 'winbind separator' parameter must "
296 "be a single character.\n\n");
297 ret = 1;
298 }
299
300 if (*lp_winbind_separator() == '+') {
301 fprintf(stderr, "'winbind separator = +' might cause problems "
302 "with group membership.\n\n");
303 }
304
305 if (lp_algorithmic_rid_base() < BASE_RID) {
306 /* Try to prevent admin foot-shooting, we can't put algorithmic
307 rids below 1000, that's the 'well known RIDs' on NT */
308 fprintf(stderr, "'algorithmic rid base' must be equal to or "
309 "above %lu\n\n", BASE_RID);
310 }
311
312 if (lp_algorithmic_rid_base() & 1) {
313 fprintf(stderr, "'algorithmic rid base' must be even.\n\n");
314 }
315
316#ifndef HAVE_DLOPEN
317 if (lp_preload_modules()) {
318 fprintf(stderr, "WARNING: 'preload modules = ' set while loading "
319 "plugins not supported.\n\n");
320 }
321#endif
322
323 if (!lp_passdb_backend()) {
324 fprintf(stderr, "ERROR: passdb backend must have a value or be "
325 "left out\n\n");
326 }
327
328 if (lp_os_level() > 255) {
329 fprintf(stderr, "WARNING: Maximum value for 'os level' is "
330 "255!\n\n");
331 }
332
333 if (strequal(lp_dos_charset(), "UTF8") || strequal(lp_dos_charset(), "UTF-8")) {
334 fprintf(stderr, "ERROR: 'dos charset' must not be UTF8\n\n");
335 ret = 1;
336 }
337
338 return ret;
339}
340
341/**
342 * per-share logic tests
343 */
344static void do_per_share_checks(int s)
345{
346 const char **deny_list = lp_hosts_deny(s);
347 const char **allow_list = lp_hosts_allow(s);
348 int i;
349
350 if(deny_list) {
351 for (i=0; deny_list[i]; i++) {
352 char *hasstar = strchr_m(deny_list[i], '*');
353 char *hasquery = strchr_m(deny_list[i], '?');
354 if(hasstar || hasquery) {
355 fprintf(stderr,
356 "Invalid character %c in hosts deny list "
357 "(%s) for service %s.\n\n",
358 hasstar ? *hasstar : *hasquery,
359 deny_list[i],
360 lp_servicename(talloc_tos(), s));
361 }
362 }
363 }
364
365 if(allow_list) {
366 for (i=0; allow_list[i]; i++) {
367 char *hasstar = strchr_m(allow_list[i], '*');
368 char *hasquery = strchr_m(allow_list[i], '?');
369 if(hasstar || hasquery) {
370 fprintf(stderr,
371 "Invalid character %c in hosts allow "
372 "list (%s) for service %s.\n\n",
373 hasstar ? *hasstar : *hasquery,
374 allow_list[i],
375 lp_servicename(talloc_tos(), s));
376 }
377 }
378 }
379
380 if(lp_level2_oplocks(s) && !lp_oplocks(s)) {
381 fprintf(stderr, "Invalid combination of parameters for service "
382 "%s. Level II oplocks can only be set if oplocks "
383 "are also set.\n\n",
384 lp_servicename(talloc_tos(), s));
385 }
386
387 if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
388 && !(lp_create_mask(s) & S_IXOTH))
389 {
390 fprintf(stderr,
391 "Invalid combination of parameters for service %s. Map "
392 "hidden can only work if create mask includes octal "
393 "01 (S_IXOTH).\n\n",
394 lp_servicename(talloc_tos(), s));
395 }
396 if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
397 && (lp_force_create_mode(s) & S_IXOTH))
398 {
399 fprintf(stderr,
400 "Invalid combination of parameters for service "
401 "%s. Map hidden can only work if force create mode "
402 "excludes octal 01 (S_IXOTH).\n\n",
403 lp_servicename(talloc_tos(), s));
404 }
405 if (!lp_store_dos_attributes(s) && lp_map_system(s)
406 && !(lp_create_mask(s) & S_IXGRP))
407 {
408 fprintf(stderr,
409 "Invalid combination of parameters for service "
410 "%s. Map system can only work if create mask includes "
411 "octal 010 (S_IXGRP).\n\n",
412 lp_servicename(talloc_tos(), s));
413 }
414 if (!lp_store_dos_attributes(s) && lp_map_system(s)
415 && (lp_force_create_mode(s) & S_IXGRP))
416 {
417 fprintf(stderr,
418 "Invalid combination of parameters for service "
419 "%s. Map system can only work if force create mode "
420 "excludes octal 010 (S_IXGRP).\n\n",
421 lp_servicename(talloc_tos(), s));
422 }
423 if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(talloc_tos(), s)) != '\0') {
424 fprintf(stderr,
425 "Warning: Service %s defines a print command, but "
426 "parameter is ignored when using CUPS libraries.\n\n",
427 lp_servicename(talloc_tos(), s));
428 }
429}
430
431 int main(int argc, const char *argv[])
432{
433 const char *config_file = get_dyn_CONFIGFILE();
434 int s;
435 static int silent_mode = False;
436 static int show_all_parameters = False;
437 int ret = 0;
438 poptContext pc;
439 static char *parameter_name = NULL;
440 static const char *section_name = NULL;
441 const char *cname;
442 const char *caddr;
443 static int show_defaults;
444 static int skip_logic_checks = 0;
445
446 struct poptOption long_options[] = {
447 POPT_AUTOHELP
448 {"suppress-prompt", 's', POPT_ARG_VAL, &silent_mode, 1, "Suppress prompt for enter"},
449 {"verbose", 'v', POPT_ARG_NONE, &show_defaults, 1, "Show default options too"},
450 {"skip-logic-checks", 'l', POPT_ARG_NONE, &skip_logic_checks, 1, "Skip the global checks"},
451 {"show-all-parameters", '\0', POPT_ARG_VAL, &show_all_parameters, True, "Show the parameters, type, possible values" },
452 {"parameter-name", '\0', POPT_ARG_STRING, &parameter_name, 0, "Limit testparm to a named parameter" },
453 {"section-name", '\0', POPT_ARG_STRING, &section_name, 0, "Limit testparm to a named section" },
454 POPT_COMMON_VERSION
455 POPT_COMMON_DEBUGLEVEL
456 POPT_COMMON_OPTION
457 POPT_TABLEEND
458 };
459
460 TALLOC_CTX *frame = talloc_stackframe();
461
462 smb_init_locale();
463 /*
464 * Set the default debug level to 2.
465 * Allow it to be overridden by the command line,
466 * not by smb.conf.
467 */
468 lp_set_cmdline("log level", "2");
469
470 pc = poptGetContext(NULL, argc, argv, long_options,
471 POPT_CONTEXT_KEEP_FIRST);
472 poptSetOtherOptionHelp(pc, "[OPTION...] <config-file> [host-name] [host-ip]");
473
474 while(poptGetNextOpt(pc) != -1);
475
476 if (show_all_parameters) {
477 show_parameter_list();
478 exit(0);
479 }
480
481 setup_logging(poptGetArg(pc), DEBUG_STDERR);
482
483 if (poptPeekArg(pc))
484 config_file = poptGetArg(pc);
485
486 cname = poptGetArg(pc);
487 caddr = poptGetArg(pc);
488
489 poptFreeContext(pc);
490
491 if ( cname && ! caddr ) {
492 printf ( "ERROR: You must specify both a machine name and an IP address.\n" );
493 ret = 1;
494 goto done;
495 }
496
497 fprintf(stderr,"Load smb config files from %s\n",config_file);
498
499 if (!lp_load_with_registry_shares(config_file)) {
500 fprintf(stderr,"Error loading services.\n");
501 ret = 1;
502 goto done;
503 }
504
505 fprintf(stderr,"Loaded services file OK.\n");
506
507 if (skip_logic_checks == 0) {
508 ret = do_global_checks();
509 }
510
511 for (s=0;s<1000;s++) {
512 if (VALID_SNUM(s))
513 if (strlen(lp_servicename(talloc_tos(), s)) > 12) {
514 fprintf(stderr, "WARNING: You have some share names that are longer than 12 characters.\n" );
515 fprintf(stderr, "These may not be accessible to some older clients.\n" );
516 fprintf(stderr, "(Eg. Windows9x, WindowsMe, and smbclient prior to Samba 3.0.)\n" );
517 break;
518 }
519 }
520
521 for (s=0;s<1000;s++) {
522 if (VALID_SNUM(s) && (skip_logic_checks == 0)) {
523 do_per_share_checks(s);
524 }
525 }
526
527
528 if (!section_name && !parameter_name) {
529 fprintf(stderr,
530 "Server role: %s\n\n",
531 server_role_str(lp_server_role()));
532 }
533
534 if (!cname) {
535 if (!silent_mode) {
536 fprintf(stderr,"Press enter to see a dump of your service definitions\n");
537 fflush(stdout);
538 getc(stdin);
539 }
540 if (parameter_name || section_name) {
541 bool isGlobal = False;
542 s = GLOBAL_SECTION_SNUM;
543
544 if (!section_name) {
545 section_name = GLOBAL_NAME;
546 isGlobal = True;
547 } else if ((isGlobal=!strwicmp(section_name, GLOBAL_NAME)) == 0 &&
548 (s=lp_servicenumber(section_name)) == -1) {
549 fprintf(stderr,"Unknown section %s\n",
550 section_name);
551 ret = 1;
552 goto done;
553 }
554 if (parameter_name) {
555 if (!dump_a_parameter( s, parameter_name, stdout, isGlobal)) {
556 fprintf(stderr,"Parameter %s unknown for section %s\n",
557 parameter_name, section_name);
558 ret = 1;
559 goto done;
560 }
561 } else {
562 if (isGlobal == True)
563 lp_dump(stdout, show_defaults, 0);
564 else
565 lp_dump_one(stdout, show_defaults, s);
566 }
567 goto done;
568 }
569
570 lp_dump(stdout, show_defaults, lp_numservices());
571 }
572
573 if(cname && caddr){
574 /* this is totally ugly, a real `quick' hack */
575 for (s=0;s<1000;s++) {
576 if (VALID_SNUM(s)) {
577 if (allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1), cname, caddr)
578 && allow_access(lp_hosts_deny(s), lp_hosts_allow(s), cname, caddr)) {
579 fprintf(stderr,"Allow connection from %s (%s) to %s\n",
580 cname,caddr,lp_servicename(talloc_tos(), s));
581 } else {
582 fprintf(stderr,"Deny connection from %s (%s) to %s\n",
583 cname,caddr,lp_servicename(talloc_tos(), s));
584 }
585 }
586 }
587 }
588
589done:
590 gfree_loadparm();
591 TALLOC_FREE(frame);
592 return ret;
593}
594
Note: See TracBrowser for help on using the repository browser.