s3/utils: Add warning to testparm for "client ipc signing" param values
[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 (lp_client_ipc_signing() == SMB_SIGNING_IF_REQUIRED
233          || lp_client_ipc_signing() == SMB_SIGNING_OFF) {
234                 fprintf(stderr, "WARNING: The 'client ipc signing' value "
235                         "%s SMB signing is not used when contacting a "
236                         "domain controller or other server. "
237                         "This setting is not recommended; please be "
238                         "aware of the security implications when using "
239                         "this configuration setting.\n\n",
240                         lp_client_ipc_signing() == SMB_SIGNING_OFF ?
241                         "ensures" : "may mean");
242         }
243
244         if (strlen(lp_netbios_name()) > 15) {
245                 fprintf(stderr, "WARNING: The 'netbios name' is too long "
246                                 "(max. 15 chars).\n\n");
247         }
248
249         if (!directory_exist_stat(lp_lock_directory(), &st)) {
250                 fprintf(stderr, "ERROR: lock directory %s does not exist\n\n",
251                        lp_lock_directory());
252                 ret = 1;
253         } else if ((st.st_ex_mode & 0777) != 0755) {
254                 fprintf(stderr, "WARNING: lock directory %s should have "
255                                 "permissions 0755 for browsing to work\n\n",
256                        lp_lock_directory());
257         }
258
259         if (!directory_exist_stat(lp_state_directory(), &st)) {
260                 fprintf(stderr, "ERROR: state directory %s does not exist\n\n",
261                        lp_state_directory());
262                 ret = 1;
263         } else if ((st.st_ex_mode & 0777) != 0755) {
264                 fprintf(stderr, "WARNING: state directory %s should have "
265                                 "permissions 0755 for browsing to work\n\n",
266                        lp_state_directory());
267         }
268
269         if (!directory_exist_stat(lp_cache_directory(), &st)) {
270                 fprintf(stderr, "ERROR: cache directory %s does not exist\n\n",
271                        lp_cache_directory());
272                 ret = 1;
273         } else if ((st.st_ex_mode & 0777) != 0755) {
274                 fprintf(stderr, "WARNING: cache directory %s should have "
275                                 "permissions 0755 for browsing to work\n\n",
276                        lp_cache_directory());
277         }
278
279         if (!directory_exist_stat(lp_pid_directory(), &st)) {
280                 fprintf(stderr, "ERROR: pid directory %s does not exist\n\n",
281                        lp_pid_directory());
282                 ret = 1;
283         }
284
285         if (lp_passdb_expand_explicit()) {
286                 fprintf(stderr, "WARNING: passdb expand explicit = yes is "
287                                 "deprecated\n\n");
288         }
289
290         /*
291          * Socket options.
292          */
293         socket_options = lp_socket_options();
294         if (socket_options != NULL &&
295             (strstr(socket_options, "SO_SNDBUF") ||
296              strstr(socket_options, "SO_RCVBUF") ||
297              strstr(socket_options, "SO_SNDLOWAT") ||
298              strstr(socket_options, "SO_RCVLOWAT")))
299         {
300                 fprintf(stderr,
301                         "WARNING: socket options = %s\n"
302                         "This warning is printed because you set one of the\n"
303                         "following options: SO_SNDBUF, SO_RCVBUF, SO_SNDLOWAT,\n"
304                         "SO_RCVLOWAT\n"
305                         "Modern server operating systems are tuned for\n"
306                         "high network performance in the majority of situations;\n"
307                         "when you set 'socket options' you are overriding those\n"
308                         "settings.\n"
309                         "Linux in particular has an auto-tuning mechanism for\n"
310                         "buffer sizes (SO_SNDBUF, SO_RCVBUF) that will be\n"
311                         "disabled if you specify a socket buffer size. This can\n"
312                         "potentially cripple your TCP/IP stack.\n\n"
313                         "Getting the 'socket options' correct can make a big\n"
314                         "difference to your performance, but getting them wrong\n"
315                         "can degrade it by just as much. As with any other low\n"
316                         "level setting, if you must make changes to it, make\n "
317                         "small changes and test the effect before making any\n"
318                         "large changes.\n\n",
319                         socket_options);
320         }
321
322         /*
323          * Password server sanity checks.
324          */
325
326         if((lp_security() >= SEC_DOMAIN) && !*lp_password_server()) {
327                 const char *sec_setting;
328                 if(lp_security() == SEC_DOMAIN)
329                         sec_setting = "domain";
330                 else if(lp_security() == SEC_ADS)
331                         sec_setting = "ads";
332                 else
333                         sec_setting = "";
334
335                 fprintf(stderr, "ERROR: The setting 'security=%s' requires the "
336                                 "'password server' parameter be set to the "
337                                 "default value * or a valid password server.\n\n",
338                                 sec_setting );
339                 ret = 1;
340         }
341
342         if((lp_security() >= SEC_DOMAIN) && (strcmp(lp_password_server(), "*") != 0)) {
343                 const char *sec_setting;
344                 if(lp_security() == SEC_DOMAIN)
345                         sec_setting = "domain";
346                 else if(lp_security() == SEC_ADS)
347                         sec_setting = "ads";
348                 else
349                         sec_setting = "";
350
351                 fprintf(stderr, "WARNING: The setting 'security=%s' should NOT "
352                                 "be combined with the 'password server' "
353                                 "parameter.\n"
354                                 "(by default Samba will discover the correct DC "
355                                 "to contact automatically).\n\n",
356                                 sec_setting );
357         }
358
359         /*
360          * Password chat sanity checks.
361          */
362
363         if(lp_security() == SEC_USER && lp_unix_password_sync()) {
364
365                 /*
366                  * Check that we have a valid lp_passwd_program() if not using pam.
367                  */
368
369 #ifdef WITH_PAM
370                 if (!lp_pam_password_change()) {
371 #endif
372
373                         if((lp_passwd_program(talloc_tos()) == NULL) ||
374                            (strlen(lp_passwd_program(talloc_tos())) == 0))
375                         {
376                                 fprintf(stderr,
377                                         "ERROR: the 'unix password sync' "
378                                         "parameter is set and there is no valid "
379                                         "'passwd program' parameter.\n\n");
380                                 ret = 1;
381                         } else {
382                                 const char *passwd_prog;
383                                 char *truncated_prog = NULL;
384                                 const char *p;
385
386                                 passwd_prog = lp_passwd_program(talloc_tos());
387                                 p = passwd_prog;
388                                 next_token_talloc(talloc_tos(),
389                                                 &p,
390                                                 &truncated_prog, NULL);
391                                 if (truncated_prog && access(truncated_prog, F_OK) == -1) {
392                                         fprintf(stderr,
393                                                 "ERROR: the 'unix password sync' "
394                                                 "parameter is set and the "
395                                                 "'passwd program' (%s) cannot be "
396                                                 "executed (error was %s).\n\n",
397                                                 truncated_prog,
398                                                 strerror(errno));
399                                         ret = 1;
400                                 }
401                         }
402
403 #ifdef WITH_PAM
404                 }
405 #endif
406
407                 if(lp_passwd_chat(talloc_tos()) == NULL) {
408                         fprintf(stderr,
409                                 "ERROR: the 'unix password sync' parameter is "
410                                 "set and there is no valid 'passwd chat' "
411                                 "parameter.\n\n");
412                         ret = 1;
413                 }
414
415                 if ((lp_passwd_program(talloc_tos()) != NULL) &&
416                     (strlen(lp_passwd_program(talloc_tos())) > 0))
417                 {
418                         /* check if there's a %u parameter present */
419                         if(strstr_m(lp_passwd_program(talloc_tos()), "%u") == NULL) {
420                                 fprintf(stderr,
421                                         "ERROR: the 'passwd program' (%s) "
422                                         "requires a '%%u' parameter.\n\n",
423                                         lp_passwd_program(talloc_tos()));
424                                 ret = 1;
425                         }
426                 }
427
428                 /*
429                  * Check that we have a valid script and that it hasn't
430                  * been written to expect the old password.
431                  */
432
433                 if(lp_encrypt_passwords()) {
434                         if(strstr_m( lp_passwd_chat(talloc_tos()), "%o")!=NULL) {
435                                 fprintf(stderr,
436                                         "ERROR: the 'passwd chat' script [%s] "
437                                         "expects to use the old plaintext "
438                                         "password via the %%o substitution. With "
439                                         "encrypted passwords this is not "
440                                         "possible.\n\n",
441                                         lp_passwd_chat(talloc_tos()) );
442                                 ret = 1;
443                         }
444                 }
445         }
446
447         if (strlen(lp_winbind_separator()) != 1) {
448                 fprintf(stderr, "ERROR: the 'winbind separator' parameter must "
449                                 "be a single character.\n\n");
450                 ret = 1;
451         }
452
453         if (*lp_winbind_separator() == '+') {
454                 fprintf(stderr, "'winbind separator = +' might cause problems "
455                                 "with group membership.\n\n");
456         }
457
458         if (lp_algorithmic_rid_base() < BASE_RID) {
459                 /* Try to prevent admin foot-shooting, we can't put algorithmic
460                    rids below 1000, that's the 'well known RIDs' on NT */
461                 fprintf(stderr, "'algorithmic rid base' must be equal to or "
462                                 "above %lu\n\n", BASE_RID);
463         }
464
465         if (lp_algorithmic_rid_base() & 1) {
466                 fprintf(stderr, "'algorithmic rid base' must be even.\n\n");
467         }
468
469         if (lp_server_role() != ROLE_STANDALONE) {
470                 const char *default_backends[] = {
471                         "tdb", "tdb2", "ldap", "autorid", "hash"
472                 };
473                 const char *idmap_backend;
474                 bool valid_backend = false;
475                 uint32_t i;
476                 bool ok;
477
478                 idmap_backend = lp_idmap_default_backend();
479
480                 for (i = 0; i < ARRAY_SIZE(default_backends); i++) {
481                         ok = strequal(idmap_backend, default_backends[i]);
482                         if (ok) {
483                                 valid_backend = true;
484                         }
485                 }
486
487                 if (!valid_backend) {
488                         ret = 1;
489                         fprintf(stderr, "ERROR: Do not use the '%s' backend "
490                                         "as the default idmap backend!\n\n",
491                                         idmap_backend);
492                 }
493
494                 ok = do_idmap_check();
495                 if (!ok) {
496                         ret = 1;
497                 }
498         }
499
500 #ifndef HAVE_DLOPEN
501         if (lp_preload_modules()) {
502                 fprintf(stderr, "WARNING: 'preload modules = ' set while loading "
503                                 "plugins not supported.\n\n");
504         }
505 #endif
506
507         if (!lp_passdb_backend()) {
508                 fprintf(stderr, "ERROR: passdb backend must have a value or be "
509                                 "left out\n\n");
510         }
511
512         if (lp_os_level() > 255) {
513                 fprintf(stderr, "WARNING: Maximum value for 'os level' is "
514                                 "255!\n\n");
515         }
516
517         if (strequal(lp_dos_charset(), "UTF8") || strequal(lp_dos_charset(), "UTF-8")) {
518                 fprintf(stderr, "ERROR: 'dos charset' must not be UTF8\n\n");
519                 ret = 1;
520         }
521
522         return ret;
523 }
524
525 /**
526  * per-share logic tests
527  */
528 static void do_per_share_checks(int s)
529 {
530         const char **deny_list = lp_hosts_deny(s);
531         const char **allow_list = lp_hosts_allow(s);
532         const char **vfs_objects = NULL;
533         int i;
534         static bool uses_fruit;
535         static bool doesnt_use_fruit;
536         static bool fruit_mix_warned;
537
538         if(deny_list) {
539                 for (i=0; deny_list[i]; i++) {
540                         char *hasstar = strchr_m(deny_list[i], '*');
541                         char *hasquery = strchr_m(deny_list[i], '?');
542                         if(hasstar || hasquery) {
543                                 fprintf(stderr,
544                                         "Invalid character %c in hosts deny list "
545                                         "(%s) for service %s.\n\n",
546                                         hasstar ? *hasstar : *hasquery,
547                                         deny_list[i],
548                                         lp_servicename(talloc_tos(), s));
549                         }
550                 }
551         }
552
553         if(allow_list) {
554                 for (i=0; allow_list[i]; i++) {
555                         char *hasstar = strchr_m(allow_list[i], '*');
556                         char *hasquery = strchr_m(allow_list[i], '?');
557                         if(hasstar || hasquery) {
558                                 fprintf(stderr,
559                                         "Invalid character %c in hosts allow "
560                                         "list (%s) for service %s.\n\n",
561                                         hasstar ? *hasstar : *hasquery,
562                                         allow_list[i],
563                                         lp_servicename(talloc_tos(), s));
564                         }
565                 }
566         }
567
568         if(lp_level2_oplocks(s) && !lp_oplocks(s)) {
569                 fprintf(stderr, "Invalid combination of parameters for service "
570                                 "%s. Level II oplocks can only be set if oplocks "
571                                 "are also set.\n\n",
572                                 lp_servicename(talloc_tos(), s));
573         }
574
575         if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
576             && !(lp_create_mask(s) & S_IXOTH))
577         {
578                 fprintf(stderr,
579                         "Invalid combination of parameters for service %s. Map "
580                         "hidden can only work if create mask includes octal "
581                         "01 (S_IXOTH).\n\n",
582                         lp_servicename(talloc_tos(), s));
583         }
584         if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
585             && (lp_force_create_mode(s) & S_IXOTH))
586         {
587                 fprintf(stderr,
588                         "Invalid combination of parameters for service "
589                         "%s. Map hidden can only work if force create mode "
590                         "excludes octal 01 (S_IXOTH).\n\n",
591                         lp_servicename(talloc_tos(), s));
592         }
593         if (!lp_store_dos_attributes(s) && lp_map_system(s)
594             && !(lp_create_mask(s) & S_IXGRP))
595         {
596                 fprintf(stderr,
597                         "Invalid combination of parameters for service "
598                         "%s. Map system can only work if create mask includes "
599                         "octal 010 (S_IXGRP).\n\n",
600                         lp_servicename(talloc_tos(), s));
601         }
602         if (!lp_store_dos_attributes(s) && lp_map_system(s)
603             && (lp_force_create_mode(s) & S_IXGRP))
604         {
605                 fprintf(stderr,
606                         "Invalid combination of parameters for service "
607                         "%s. Map system can only work if force create mode "
608                         "excludes octal 010 (S_IXGRP).\n\n",
609                         lp_servicename(talloc_tos(), s));
610         }
611         if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(talloc_tos(), s)) != '\0') {
612                 fprintf(stderr,
613                         "Warning: Service %s defines a print command, but "
614                         "parameter is ignored when using CUPS libraries.\n\n",
615                         lp_servicename(talloc_tos(), s));
616         }
617
618         vfs_objects = lp_vfs_objects(s);
619         if (vfs_objects && str_list_check(vfs_objects, "fruit")) {
620                 uses_fruit = true;
621         } else {
622                 doesnt_use_fruit = true;
623         }
624
625         if (uses_fruit && doesnt_use_fruit && !fruit_mix_warned) {
626                 fruit_mix_warned = true;
627                 fprintf(stderr,
628                         "WARNING: some services use vfs_fruit, others don't. Mounting them "
629                         "in conjunction on OS X clients results in undefined behaviour.\n\n");
630         }
631 }
632
633  int main(int argc, const char *argv[])
634 {
635         const char *config_file = get_dyn_CONFIGFILE();
636         int s;
637         static int silent_mode = False;
638         static int show_all_parameters = False;
639         int ret = 0;
640         poptContext pc;
641         static char *parameter_name = NULL;
642         static const char *section_name = NULL;
643         const char *cname;
644         const char *caddr;
645         static int show_defaults;
646         static int skip_logic_checks = 0;
647
648         struct poptOption long_options[] = {
649                 POPT_AUTOHELP
650                 {"suppress-prompt", 's', POPT_ARG_VAL, &silent_mode, 1, "Suppress prompt for enter"},
651                 {"verbose", 'v', POPT_ARG_NONE, &show_defaults, 1, "Show default options too"},
652                 {"skip-logic-checks", 'l', POPT_ARG_NONE, &skip_logic_checks, 1, "Skip the global checks"},
653                 {"show-all-parameters", '\0', POPT_ARG_VAL, &show_all_parameters, True, "Show the parameters, type, possible values" },
654                 {"parameter-name", '\0', POPT_ARG_STRING, &parameter_name, 0, "Limit testparm to a named parameter" },
655                 {"section-name", '\0', POPT_ARG_STRING, &section_name, 0, "Limit testparm to a named section" },
656                 POPT_COMMON_VERSION
657                 POPT_COMMON_DEBUGLEVEL
658                 POPT_COMMON_OPTION
659                 POPT_TABLEEND
660         };
661
662         TALLOC_CTX *frame = talloc_stackframe();
663
664         smb_init_locale();
665         /*
666          * Set the default debug level to 2.
667          * Allow it to be overridden by the command line,
668          * not by smb.conf.
669          */
670         lp_set_cmdline("log level", "2");
671
672         pc = poptGetContext(NULL, argc, argv, long_options,
673                             POPT_CONTEXT_KEEP_FIRST);
674         poptSetOtherOptionHelp(pc, "[OPTION...] <config-file> [host-name] [host-ip]");
675
676         while(poptGetNextOpt(pc) != -1);
677
678         if (show_all_parameters) {
679                 show_parameter_list();
680                 exit(0);
681         }
682
683         setup_logging(poptGetArg(pc), DEBUG_STDERR);
684
685         if (poptPeekArg(pc))
686                 config_file = poptGetArg(pc);
687
688         cname = poptGetArg(pc);
689         caddr = poptGetArg(pc);
690
691         poptFreeContext(pc);
692
693         if ( cname && ! caddr ) {
694                 printf ( "ERROR: You must specify both a machine name and an IP address.\n" );
695                 ret = 1;
696                 goto done;
697         }
698
699         fprintf(stderr,"Load smb config files from %s\n",config_file);
700
701         if (!lp_load_with_registry_shares(config_file)) {
702                 fprintf(stderr,"Error loading services.\n");
703                 ret = 1;
704                 goto done;
705         }
706
707         fprintf(stderr,"Loaded services file OK.\n");
708
709         if (skip_logic_checks == 0) {
710                 ret = do_global_checks();
711         }
712
713         for (s=0;s<1000;s++) {
714                 if (VALID_SNUM(s))
715                         if (strlen(lp_servicename(talloc_tos(), s)) > 12) {
716                                 fprintf(stderr, "WARNING: You have some share names that are longer than 12 characters.\n" );
717                                 fprintf(stderr, "These may not be accessible to some older clients.\n" );
718                                 fprintf(stderr, "(Eg. Windows9x, WindowsMe, and smbclient prior to Samba 3.0.)\n" );
719                                 break;
720                         }
721         }
722
723         for (s=0;s<1000;s++) {
724                 if (VALID_SNUM(s) && (skip_logic_checks == 0)) {
725                         do_per_share_checks(s);
726                 }
727         }
728
729
730         if (!section_name && !parameter_name) {
731                 fprintf(stderr,
732                         "Server role: %s\n\n",
733                         server_role_str(lp_server_role()));
734         }
735
736         if (!cname) {
737                 if (!silent_mode) {
738                         fprintf(stderr,"Press enter to see a dump of your service definitions\n");
739                         fflush(stdout);
740                         getc(stdin);
741                 }
742                 if (parameter_name || section_name) {
743                         bool isGlobal = False;
744                         s = GLOBAL_SECTION_SNUM;
745
746                         if (!section_name) {
747                                 section_name = GLOBAL_NAME;
748                                 isGlobal = True;
749                         } else if ((isGlobal=!strwicmp(section_name, GLOBAL_NAME)) == 0 &&
750                                  (s=lp_servicenumber(section_name)) == -1) {
751                                         fprintf(stderr,"Unknown section %s\n",
752                                                 section_name);
753                                         ret = 1;
754                                         goto done;
755                         }
756                         if (parameter_name) {
757                                 if (!dump_a_parameter( s, parameter_name, stdout, isGlobal)) {
758                                         fprintf(stderr,"Parameter %s unknown for section %s\n",
759                                                 parameter_name, section_name);
760                                         ret = 1;
761                                         goto done;
762                                 }
763                         } else {
764                                 if (isGlobal == True)
765                                         lp_dump(stdout, show_defaults, 0);
766                                 else
767                                         lp_dump_one(stdout, show_defaults, s);
768                         }
769                         goto done;
770                 }
771
772                 lp_dump(stdout, show_defaults, lp_numservices());
773         }
774
775         if(cname && caddr){
776                 /* this is totally ugly, a real `quick' hack */
777                 for (s=0;s<1000;s++) {
778                         if (VALID_SNUM(s)) {
779                                 if (allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1), cname, caddr)
780                                     && allow_access(lp_hosts_deny(s), lp_hosts_allow(s), cname, caddr)) {
781                                         fprintf(stderr,"Allow connection from %s (%s) to %s\n",
782                                                    cname,caddr,lp_servicename(talloc_tos(), s));
783                                 } else {
784                                         fprintf(stderr,"Deny connection from %s (%s) to %s\n",
785                                                    cname,caddr,lp_servicename(talloc_tos(), s));
786                                 }
787                         }
788                 }
789         }
790
791 done:
792         gfree_loadparm();
793         TALLOC_FREE(frame);
794         return ret;
795 }
796