7883bca135cbbc562bfa071c8f171fd0d58c8e99
[metze/samba/wip.git] / source3 / utils / testparm.c
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 #include <regex.h>
40
41 /*******************************************************************
42  Check if a directory exists.
43 ********************************************************************/
44
45 static bool directory_exist_stat(const char *dname,SMB_STRUCT_STAT *st)
46 {
47         SMB_STRUCT_STAT st2;
48         bool ret;
49
50         if (!st)
51                 st = &st2;
52
53         if (sys_stat(dname, st, false) != 0)
54                 return(False);
55
56         ret = S_ISDIR(st->st_ex_mode);
57         if(!ret)
58                 errno = ENOTDIR;
59         return ret;
60 }
61
62 struct idmap_config {
63         const char *domain_name;
64         const char *backend;
65         uint32_t high;
66         uint32_t low;
67 };
68
69 struct idmap_domains {
70         struct idmap_config *c;
71         uint32_t count;
72         uint32_t size;
73 };
74
75 static bool lp_scan_idmap_found_domain(const char *string,
76                                        regmatch_t matches[],
77                                        void *private_data)
78 {
79         bool ok = false;
80
81         if (matches[1].rm_so == -1) {
82                 fprintf(stderr, "Found match, but no name - invalid idmap config");
83                 return false;
84         }
85         if (matches[1].rm_eo <= matches[1].rm_so) {
86                 fprintf(stderr, "Invalid match - invalid idmap config");
87                 return false;
88         }
89
90         {
91                 struct idmap_domains *d = private_data;
92                 struct idmap_config *c = &d->c[d->count];
93                 regoff_t len = matches[1].rm_eo - matches[1].rm_so;
94                 char domname[len + 1];
95
96                 if (d->count >= d->size) {
97                         return false;
98                 }
99
100                 memcpy(domname, string + matches[1].rm_so, len);
101                 domname[len] = '\0';
102
103                 c->domain_name = talloc_strdup_upper(d->c, domname);
104                 if (c->domain_name == NULL) {
105                         return false;
106                 }
107                 c->backend = talloc_strdup(d->c, lp_idmap_backend(domname));
108                 if (c->backend == NULL) {
109                         return false;
110                 }
111
112                 ok = lp_idmap_range(domname, &c->low, &c->high);
113                 if (!ok) {
114                         fprintf(stderr,
115                                 "ERROR: Invalid idmap range for domain "
116                                 "%s!\n\n",
117                                 c->domain_name);
118                         return false;
119                 }
120
121                 d->count++;
122         }
123
124         return false; /* Keep scanning */
125 }
126
127 static bool do_idmap_check(void)
128 {
129         struct idmap_domains *d;
130         uint32_t i;
131         bool ok = false;
132         int rc;
133
134         d = talloc_zero(talloc_tos(), struct idmap_domains);
135         if (d == NULL) {
136                 return false;
137         }
138         d->count = 0;
139         d->size = 32;
140
141         d->c = talloc_array(d, struct idmap_config, d->size);
142         if (d->c == NULL) {
143                 goto done;
144         }
145
146         rc = lp_wi_scan_global_parametrics("idmapconfig\\(.*\\):backend",
147                                            2,
148                                            lp_scan_idmap_found_domain,
149                                            d);
150         if (rc != 0) {
151                 fprintf(stderr,
152                         "FATAL: wi_scan_global_parametrics failed: %d",
153                         rc);
154         }
155
156         for (i = 0; i < d->count; i++) {
157                 struct idmap_config *c = &d->c[i];
158                 uint32_t j;
159
160                 for (j = 0; j < d->count && j != i; j++) {
161                         struct idmap_config *x = &d->c[j];
162
163                         if ((c->low >= x->low && c->low <= x->high) ||
164                             (c->high >= x->low && c->high <= x->high)) {
165                                 /* Allow overlapping ranges for idmap_ad */
166                                 ok = strequal(c->backend, x->backend);
167                                 if (ok) {
168                                         ok = strequal(c->backend, "ad");
169                                         if (ok) {
170                                                 fprintf(stderr,
171                                                         "NOTE: The idmap_ad "
172                                                         "range for the domain "
173                                                         "%s overlaps with the "
174                                                         "range of %s.\n\n",
175                                                         c->domain_name,
176                                                         x->domain_name);
177                                                 continue;
178                                         }
179                                 }
180
181                                 fprintf(stderr,
182                                         "ERROR: The idmap range for the domain "
183                                         "%s (%s) overlaps with the range of "
184                                         "%s (%s)!\n\n",
185                                         c->domain_name,
186                                         c->backend,
187                                         x->domain_name,
188                                         x->backend);
189                                 ok = false;
190                                 goto done;
191                         }
192                 }
193         }
194
195         ok = true;
196 done:
197         TALLOC_FREE(d);
198         return ok;
199 }
200
201 /***********************************************
202  Here we do a set of 'hard coded' checks for bad
203  configuration settings.
204 ************************************************/
205
206 static int do_global_checks(void)
207 {
208         int ret = 0;
209         SMB_STRUCT_STAT st;
210         const char *socket_options;
211
212         if (lp_security() >= SEC_DOMAIN && !lp_encrypt_passwords()) {
213                 fprintf(stderr, "ERROR: in 'security=domain' mode the "
214                                 "'encrypt passwords' parameter must always be "
215                                 "set to 'true'.\n\n");
216                 ret = 1;
217         }
218
219         if (lp_we_are_a_wins_server() && lp_wins_server_list()) {
220                 fprintf(stderr, "ERROR: both 'wins support = true' and "
221                                 "'wins server = <server list>' cannot be set in "
222                                 "the smb.conf file. nmbd will abort with this "
223                                 "setting.\n\n");
224                 ret = 1;
225         }
226
227         if (strequal(lp_workgroup(), lp_netbios_name())) {
228                 fprintf(stderr, "WARNING: 'workgroup' and 'netbios name' "
229                                 "must differ.\n\n");
230         }
231
232         if (strlen(lp_netbios_name()) > 15) {
233                 fprintf(stderr, "WARNING: The 'netbios name' is too long "
234                                 "(max. 15 chars).\n\n");
235         }
236
237         if (!directory_exist_stat(lp_lock_directory(), &st)) {
238                 fprintf(stderr, "ERROR: lock directory %s does not exist\n\n",
239                        lp_lock_directory());
240                 ret = 1;
241         } else if ((st.st_ex_mode & 0777) != 0755) {
242                 fprintf(stderr, "WARNING: lock directory %s should have "
243                                 "permissions 0755 for browsing to work\n\n",
244                        lp_lock_directory());
245         }
246
247         if (!directory_exist_stat(lp_state_directory(), &st)) {
248                 fprintf(stderr, "ERROR: state directory %s does not exist\n\n",
249                        lp_state_directory());
250                 ret = 1;
251         } else if ((st.st_ex_mode & 0777) != 0755) {
252                 fprintf(stderr, "WARNING: state directory %s should have "
253                                 "permissions 0755 for browsing to work\n\n",
254                        lp_state_directory());
255         }
256
257         if (!directory_exist_stat(lp_cache_directory(), &st)) {
258                 fprintf(stderr, "ERROR: cache directory %s does not exist\n\n",
259                        lp_cache_directory());
260                 ret = 1;
261         } else if ((st.st_ex_mode & 0777) != 0755) {
262                 fprintf(stderr, "WARNING: cache directory %s should have "
263                                 "permissions 0755 for browsing to work\n\n",
264                        lp_cache_directory());
265         }
266
267         if (!directory_exist_stat(lp_pid_directory(), &st)) {
268                 fprintf(stderr, "ERROR: pid directory %s does not exist\n\n",
269                        lp_pid_directory());
270                 ret = 1;
271         }
272
273         if (lp_passdb_expand_explicit()) {
274                 fprintf(stderr, "WARNING: passdb expand explicit = yes is "
275                                 "deprecated\n\n");
276         }
277
278         /*
279          * Socket options.
280          */
281         socket_options = lp_socket_options();
282         if (socket_options != NULL &&
283             (strstr(socket_options, "SO_SNDBUF") ||
284              strstr(socket_options, "SO_RCVBUF") ||
285              strstr(socket_options, "SO_SNDLOWAT") ||
286              strstr(socket_options, "SO_RCVLOWAT")))
287         {
288                 fprintf(stderr,
289                         "WARNING: socket options = %s\n"
290                         "This warning is printed because you set one of the\n"
291                         "following options: SO_SNDBUF, SO_RCVBUF, SO_SNDLOWAT,\n"
292                         "SO_RCVLOWAT\n"
293                         "Modern server operating systems are tuned for\n"
294                         "high network performance in the majority of situations;\n"
295                         "when you set 'socket options' you are overriding those\n"
296                         "settings.\n"
297                         "Linux in particular has an auto-tuning mechanism for\n"
298                         "buffer sizes (SO_SNDBUF, SO_RCVBUF) that will be\n"
299                         "disabled if you specify a socket buffer size. This can\n"
300                         "potentially cripple your TCP/IP stack.\n\n"
301                         "Getting the 'socket options' correct can make a big\n"
302                         "difference to your performance, but getting them wrong\n"
303                         "can degrade it by just as much. As with any other low\n"
304                         "level setting, if you must make changes to it, make\n "
305                         "small changes and test the effect before making any\n"
306                         "large changes.\n\n",
307                         socket_options);
308         }
309
310         /*
311          * Password server sanity checks.
312          */
313
314         if((lp_security() >= SEC_DOMAIN) && !*lp_password_server()) {
315                 const char *sec_setting;
316                 if(lp_security() == SEC_DOMAIN)
317                         sec_setting = "domain";
318                 else if(lp_security() == SEC_ADS)
319                         sec_setting = "ads";
320                 else
321                         sec_setting = "";
322
323                 fprintf(stderr, "ERROR: The setting 'security=%s' requires the "
324                                 "'password server' parameter be set to the "
325                                 "default value * or a valid password server.\n\n",
326                                 sec_setting );
327                 ret = 1;
328         }
329
330         if((lp_security() >= SEC_DOMAIN) && (strcmp(lp_password_server(), "*") != 0)) {
331                 const char *sec_setting;
332                 if(lp_security() == SEC_DOMAIN)
333                         sec_setting = "domain";
334                 else if(lp_security() == SEC_ADS)
335                         sec_setting = "ads";
336                 else
337                         sec_setting = "";
338
339                 fprintf(stderr, "WARNING: The setting 'security=%s' should NOT "
340                                 "be combined with the 'password server' "
341                                 "parameter.\n"
342                                 "(by default Samba will discover the correct DC "
343                                 "to contact automatically).\n\n",
344                                 sec_setting );
345         }
346
347         /*
348          * Password chat sanity checks.
349          */
350
351         if(lp_security() == SEC_USER && lp_unix_password_sync()) {
352
353                 /*
354                  * Check that we have a valid lp_passwd_program() if not using pam.
355                  */
356
357 #ifdef WITH_PAM
358                 if (!lp_pam_password_change()) {
359 #endif
360
361                         if((lp_passwd_program(talloc_tos()) == NULL) ||
362                            (strlen(lp_passwd_program(talloc_tos())) == 0))
363                         {
364                                 fprintf(stderr,
365                                         "ERROR: the 'unix password sync' "
366                                         "parameter is set and there is no valid "
367                                         "'passwd program' parameter.\n\n");
368                                 ret = 1;
369                         } else {
370                                 const char *passwd_prog;
371                                 char *truncated_prog = NULL;
372                                 const char *p;
373
374                                 passwd_prog = lp_passwd_program(talloc_tos());
375                                 p = passwd_prog;
376                                 next_token_talloc(talloc_tos(),
377                                                 &p,
378                                                 &truncated_prog, NULL);
379                                 if (truncated_prog && access(truncated_prog, F_OK) == -1) {
380                                         fprintf(stderr,
381                                                 "ERROR: the 'unix password sync' "
382                                                 "parameter is set and the "
383                                                 "'passwd program' (%s) cannot be "
384                                                 "executed (error was %s).\n\n",
385                                                 truncated_prog,
386                                                 strerror(errno));
387                                         ret = 1;
388                                 }
389                         }
390
391 #ifdef WITH_PAM
392                 }
393 #endif
394
395                 if(lp_passwd_chat(talloc_tos()) == NULL) {
396                         fprintf(stderr,
397                                 "ERROR: the 'unix password sync' parameter is "
398                                 "set and there is no valid 'passwd chat' "
399                                 "parameter.\n\n");
400                         ret = 1;
401                 }
402
403                 if ((lp_passwd_program(talloc_tos()) != NULL) &&
404                     (strlen(lp_passwd_program(talloc_tos())) > 0))
405                 {
406                         /* check if there's a %u parameter present */
407                         if(strstr_m(lp_passwd_program(talloc_tos()), "%u") == NULL) {
408                                 fprintf(stderr,
409                                         "ERROR: the 'passwd program' (%s) "
410                                         "requires a '%%u' parameter.\n\n",
411                                         lp_passwd_program(talloc_tos()));
412                                 ret = 1;
413                         }
414                 }
415
416                 /*
417                  * Check that we have a valid script and that it hasn't
418                  * been written to expect the old password.
419                  */
420
421                 if(lp_encrypt_passwords()) {
422                         if(strstr_m( lp_passwd_chat(talloc_tos()), "%o")!=NULL) {
423                                 fprintf(stderr,
424                                         "ERROR: the 'passwd chat' script [%s] "
425                                         "expects to use the old plaintext "
426                                         "password via the %%o substitution. With "
427                                         "encrypted passwords this is not "
428                                         "possible.\n\n",
429                                         lp_passwd_chat(talloc_tos()) );
430                                 ret = 1;
431                         }
432                 }
433         }
434
435         if (strlen(lp_winbind_separator()) != 1) {
436                 fprintf(stderr, "ERROR: the 'winbind separator' parameter must "
437                                 "be a single character.\n\n");
438                 ret = 1;
439         }
440
441         if (*lp_winbind_separator() == '+') {
442                 fprintf(stderr, "'winbind separator = +' might cause problems "
443                                 "with group membership.\n\n");
444         }
445
446         if (lp_algorithmic_rid_base() < BASE_RID) {
447                 /* Try to prevent admin foot-shooting, we can't put algorithmic
448                    rids below 1000, that's the 'well known RIDs' on NT */
449                 fprintf(stderr, "'algorithmic rid base' must be equal to or "
450                                 "above %lu\n\n", BASE_RID);
451         }
452
453         if (lp_algorithmic_rid_base() & 1) {
454                 fprintf(stderr, "'algorithmic rid base' must be even.\n\n");
455         }
456
457         if (lp_server_role() != ROLE_STANDALONE) {
458                 const char *default_backends[] = {
459                         "tdb", "tdb2", "ldap", "autorid", "hash"
460                 };
461                 const char *idmap_backend;
462                 bool valid_backend = false;
463                 uint32_t i;
464                 bool ok;
465
466                 idmap_backend = lp_idmap_default_backend();
467
468                 for (i = 0; i < ARRAY_SIZE(default_backends); i++) {
469                         ok = strequal(idmap_backend, default_backends[i]);
470                         if (ok) {
471                                 valid_backend = true;
472                         }
473                 }
474
475                 if (!valid_backend) {
476                         ret = 1;
477                         fprintf(stderr, "ERROR: Do not use the '%s' backend "
478                                         "as the default idmap backend!\n\n",
479                                         idmap_backend);
480                 }
481
482                 ok = do_idmap_check();
483                 if (!ok) {
484                         ret = 1;
485                 }
486         }
487
488 #ifndef HAVE_DLOPEN
489         if (lp_preload_modules()) {
490                 fprintf(stderr, "WARNING: 'preload modules = ' set while loading "
491                                 "plugins not supported.\n\n");
492         }
493 #endif
494
495         if (!lp_passdb_backend()) {
496                 fprintf(stderr, "ERROR: passdb backend must have a value or be "
497                                 "left out\n\n");
498         }
499
500         if (lp_os_level() > 255) {
501                 fprintf(stderr, "WARNING: Maximum value for 'os level' is "
502                                 "255!\n\n");
503         }
504
505         if (strequal(lp_dos_charset(), "UTF8") || strequal(lp_dos_charset(), "UTF-8")) {
506                 fprintf(stderr, "ERROR: 'dos charset' must not be UTF8\n\n");
507                 ret = 1;
508         }
509
510         return ret;
511 }
512
513 /**
514  * per-share logic tests
515  */
516 static void do_per_share_checks(int s)
517 {
518         const char **deny_list = lp_hosts_deny(s);
519         const char **allow_list = lp_hosts_allow(s);
520         const char **vfs_objects = NULL;
521         int i;
522         static bool uses_fruit;
523         static bool doesnt_use_fruit;
524         static bool fruit_mix_warned;
525
526         if(deny_list) {
527                 for (i=0; deny_list[i]; i++) {
528                         char *hasstar = strchr_m(deny_list[i], '*');
529                         char *hasquery = strchr_m(deny_list[i], '?');
530                         if(hasstar || hasquery) {
531                                 fprintf(stderr,
532                                         "Invalid character %c in hosts deny list "
533                                         "(%s) for service %s.\n\n",
534                                         hasstar ? *hasstar : *hasquery,
535                                         deny_list[i],
536                                         lp_servicename(talloc_tos(), s));
537                         }
538                 }
539         }
540
541         if(allow_list) {
542                 for (i=0; allow_list[i]; i++) {
543                         char *hasstar = strchr_m(allow_list[i], '*');
544                         char *hasquery = strchr_m(allow_list[i], '?');
545                         if(hasstar || hasquery) {
546                                 fprintf(stderr,
547                                         "Invalid character %c in hosts allow "
548                                         "list (%s) for service %s.\n\n",
549                                         hasstar ? *hasstar : *hasquery,
550                                         allow_list[i],
551                                         lp_servicename(talloc_tos(), s));
552                         }
553                 }
554         }
555
556         if(lp_level2_oplocks(s) && !lp_oplocks(s)) {
557                 fprintf(stderr, "Invalid combination of parameters for service "
558                                 "%s. Level II oplocks can only be set if oplocks "
559                                 "are also set.\n\n",
560                                 lp_servicename(talloc_tos(), s));
561         }
562
563         if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
564             && !(lp_create_mask(s) & S_IXOTH))
565         {
566                 fprintf(stderr,
567                         "Invalid combination of parameters for service %s. Map "
568                         "hidden can only work if create mask includes octal "
569                         "01 (S_IXOTH).\n\n",
570                         lp_servicename(talloc_tos(), s));
571         }
572         if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
573             && (lp_force_create_mode(s) & S_IXOTH))
574         {
575                 fprintf(stderr,
576                         "Invalid combination of parameters for service "
577                         "%s. Map hidden can only work if force create mode "
578                         "excludes octal 01 (S_IXOTH).\n\n",
579                         lp_servicename(talloc_tos(), s));
580         }
581         if (!lp_store_dos_attributes(s) && lp_map_system(s)
582             && !(lp_create_mask(s) & S_IXGRP))
583         {
584                 fprintf(stderr,
585                         "Invalid combination of parameters for service "
586                         "%s. Map system can only work if create mask includes "
587                         "octal 010 (S_IXGRP).\n\n",
588                         lp_servicename(talloc_tos(), s));
589         }
590         if (!lp_store_dos_attributes(s) && lp_map_system(s)
591             && (lp_force_create_mode(s) & S_IXGRP))
592         {
593                 fprintf(stderr,
594                         "Invalid combination of parameters for service "
595                         "%s. Map system can only work if force create mode "
596                         "excludes octal 010 (S_IXGRP).\n\n",
597                         lp_servicename(talloc_tos(), s));
598         }
599         if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(talloc_tos(), s)) != '\0') {
600                 fprintf(stderr,
601                         "Warning: Service %s defines a print command, but "
602                         "parameter is ignored when using CUPS libraries.\n\n",
603                         lp_servicename(talloc_tos(), s));
604         }
605
606         vfs_objects = lp_vfs_objects(s);
607         if (vfs_objects && str_list_check(vfs_objects, "fruit")) {
608                 uses_fruit = true;
609         } else {
610                 doesnt_use_fruit = true;
611         }
612
613         if (uses_fruit && doesnt_use_fruit && !fruit_mix_warned) {
614                 fruit_mix_warned = true;
615                 fprintf(stderr,
616                         "WARNING: some services use vfs_fruit, others don't. Mounting them "
617                         "in conjunction on OS X clients results in undefined behaviour.\n\n");
618         }
619 }
620
621  int main(int argc, const char *argv[])
622 {
623         const char *config_file = get_dyn_CONFIGFILE();
624         int s;
625         static int silent_mode = False;
626         static int show_all_parameters = False;
627         int ret = 0;
628         poptContext pc;
629         static char *parameter_name = NULL;
630         static const char *section_name = NULL;
631         const char *cname;
632         const char *caddr;
633         static int show_defaults;
634         static int skip_logic_checks = 0;
635
636         struct poptOption long_options[] = {
637                 POPT_AUTOHELP
638                 {"suppress-prompt", 's', POPT_ARG_VAL, &silent_mode, 1, "Suppress prompt for enter"},
639                 {"verbose", 'v', POPT_ARG_NONE, &show_defaults, 1, "Show default options too"},
640                 {"skip-logic-checks", 'l', POPT_ARG_NONE, &skip_logic_checks, 1, "Skip the global checks"},
641                 {"show-all-parameters", '\0', POPT_ARG_VAL, &show_all_parameters, True, "Show the parameters, type, possible values" },
642                 {"parameter-name", '\0', POPT_ARG_STRING, &parameter_name, 0, "Limit testparm to a named parameter" },
643                 {"section-name", '\0', POPT_ARG_STRING, &section_name, 0, "Limit testparm to a named section" },
644                 POPT_COMMON_VERSION
645                 POPT_COMMON_DEBUGLEVEL
646                 POPT_COMMON_OPTION
647                 POPT_TABLEEND
648         };
649
650         TALLOC_CTX *frame = talloc_stackframe();
651
652         smb_init_locale();
653         /*
654          * Set the default debug level to 2.
655          * Allow it to be overridden by the command line,
656          * not by smb.conf.
657          */
658         lp_set_cmdline("log level", "2");
659
660         pc = poptGetContext(NULL, argc, argv, long_options,
661                             POPT_CONTEXT_KEEP_FIRST);
662         poptSetOtherOptionHelp(pc, "[OPTION...] <config-file> [host-name] [host-ip]");
663
664         while(poptGetNextOpt(pc) != -1);
665
666         if (show_all_parameters) {
667                 show_parameter_list();
668                 exit(0);
669         }
670
671         setup_logging(poptGetArg(pc), DEBUG_STDERR);
672
673         if (poptPeekArg(pc))
674                 config_file = poptGetArg(pc);
675
676         cname = poptGetArg(pc);
677         caddr = poptGetArg(pc);
678
679         poptFreeContext(pc);
680
681         if ( cname && ! caddr ) {
682                 printf ( "ERROR: You must specify both a machine name and an IP address.\n" );
683                 ret = 1;
684                 goto done;
685         }
686
687         fprintf(stderr,"Load smb config files from %s\n",config_file);
688
689         if (!lp_load_with_registry_shares(config_file)) {
690                 fprintf(stderr,"Error loading services.\n");
691                 ret = 1;
692                 goto done;
693         }
694
695         fprintf(stderr,"Loaded services file OK.\n");
696
697         if (skip_logic_checks == 0) {
698                 ret = do_global_checks();
699         }
700
701         for (s=0;s<1000;s++) {
702                 if (VALID_SNUM(s))
703                         if (strlen(lp_servicename(talloc_tos(), s)) > 12) {
704                                 fprintf(stderr, "WARNING: You have some share names that are longer than 12 characters.\n" );
705                                 fprintf(stderr, "These may not be accessible to some older clients.\n" );
706                                 fprintf(stderr, "(Eg. Windows9x, WindowsMe, and smbclient prior to Samba 3.0.)\n" );
707                                 break;
708                         }
709         }
710
711         for (s=0;s<1000;s++) {
712                 if (VALID_SNUM(s) && (skip_logic_checks == 0)) {
713                         do_per_share_checks(s);
714                 }
715         }
716
717
718         if (!section_name && !parameter_name) {
719                 fprintf(stderr,
720                         "Server role: %s\n\n",
721                         server_role_str(lp_server_role()));
722         }
723
724         if (!cname) {
725                 if (!silent_mode) {
726                         fprintf(stderr,"Press enter to see a dump of your service definitions\n");
727                         fflush(stdout);
728                         getc(stdin);
729                 }
730                 if (parameter_name || section_name) {
731                         bool isGlobal = False;
732                         s = GLOBAL_SECTION_SNUM;
733
734                         if (!section_name) {
735                                 section_name = GLOBAL_NAME;
736                                 isGlobal = True;
737                         } else if ((isGlobal=!strwicmp(section_name, GLOBAL_NAME)) == 0 &&
738                                  (s=lp_servicenumber(section_name)) == -1) {
739                                         fprintf(stderr,"Unknown section %s\n",
740                                                 section_name);
741                                         ret = 1;
742                                         goto done;
743                         }
744                         if (parameter_name) {
745                                 if (!dump_a_parameter( s, parameter_name, stdout, isGlobal)) {
746                                         fprintf(stderr,"Parameter %s unknown for section %s\n",
747                                                 parameter_name, section_name);
748                                         ret = 1;
749                                         goto done;
750                                 }
751                         } else {
752                                 if (isGlobal == True)
753                                         lp_dump(stdout, show_defaults, 0);
754                                 else
755                                         lp_dump_one(stdout, show_defaults, s);
756                         }
757                         goto done;
758                 }
759
760                 lp_dump(stdout, show_defaults, lp_numservices());
761         }
762
763         if(cname && caddr){
764                 /* this is totally ugly, a real `quick' hack */
765                 for (s=0;s<1000;s++) {
766                         if (VALID_SNUM(s)) {
767                                 if (allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1), cname, caddr)
768                                     && allow_access(lp_hosts_deny(s), lp_hosts_allow(s), cname, caddr)) {
769                                         fprintf(stderr,"Allow connection from %s (%s) to %s\n",
770                                                    cname,caddr,lp_servicename(talloc_tos(), s));
771                                 } else {
772                                         fprintf(stderr,"Deny connection from %s (%s) to %s\n",
773                                                    cname,caddr,lp_servicename(talloc_tos(), s));
774                                 }
775                         }
776                 }
777         }
778
779 done:
780         gfree_loadparm();
781         TALLOC_FREE(frame);
782         return ret;
783 }
784