s4:kdc: Make use of smb_krb5_principal_is_tgs()
[Samba.git] / source3 / utils / testparm.c
blobfd90e8d734a8842bc312fdc251472abaabf6e1fe
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 "lib/cmdline/cmdline.h"
37 #include "lib/param/loadparm.h"
38 #include "lib/param/param.h"
39 #include "lib/crypto/gnutls_helpers.h"
40 #include "cmdline_contexts.h"
42 #include <regex.h>
44 /*******************************************************************
45 Check if a directory exists.
46 ********************************************************************/
48 static bool directory_exist_stat(const char *dname,SMB_STRUCT_STAT *st)
50 SMB_STRUCT_STAT st2;
51 bool ret;
53 if (!st)
54 st = &st2;
56 if (sys_stat(dname, st, false) != 0)
57 return(False);
59 ret = S_ISDIR(st->st_ex_mode);
60 if(!ret)
61 errno = ENOTDIR;
62 return ret;
65 struct idmap_config {
66 const char *domain_name;
67 const char *backend;
68 uint32_t high;
69 uint32_t low;
72 struct idmap_domains {
73 struct idmap_config *c;
74 uint32_t count;
75 uint32_t size;
78 static bool lp_scan_idmap_found_domain(const char *string,
79 regmatch_t matches[],
80 void *private_data)
82 bool ok = false;
84 if (matches[1].rm_so == -1) {
85 fprintf(stderr, "Found match, but no name - invalid idmap config");
86 return false;
88 if (matches[1].rm_eo <= matches[1].rm_so) {
89 fprintf(stderr, "Invalid match - invalid idmap config");
90 return false;
94 struct idmap_domains *d = private_data;
95 struct idmap_config *c = &d->c[d->count];
96 regoff_t len = matches[1].rm_eo - matches[1].rm_so;
97 char domname[len + 1];
99 if (d->count >= d->size) {
100 return false;
103 memcpy(domname, string + matches[1].rm_so, len);
104 domname[len] = '\0';
106 c->domain_name = talloc_strdup_upper(d->c, domname);
107 if (c->domain_name == NULL) {
108 return false;
110 c->backend = talloc_strdup(d->c, lp_idmap_backend(domname));
111 if (c->backend == NULL) {
112 return false;
115 if (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) {
116 ok = lp_idmap_range(domname, &c->low, &c->high);
117 if (!ok) {
118 fprintf(stderr,
119 "ERROR: Invalid idmap range for domain "
120 "%s!\n\n",
121 c->domain_name);
122 return false;
126 d->count++;
129 return false; /* Keep scanning */
132 static int idmap_config_int(const char *domname, const char *option, int def)
134 int len = snprintf(NULL, 0, "idmap config %s", domname);
136 if (len == -1) {
137 return def;
140 char config_option[len+1];
141 snprintf(config_option, sizeof(config_option),
142 "idmap config %s", domname);
143 return lp_parm_int(-1, config_option, option, def);
147 static bool do_idmap_check(void)
149 struct idmap_domains *d;
150 uint32_t i;
151 bool ok = false;
152 int rc;
154 d = talloc_zero(talloc_tos(), struct idmap_domains);
155 if (d == NULL) {
156 return false;
158 d->count = 0;
159 d->size = 32;
161 d->c = talloc_array(d, struct idmap_config, d->size);
162 if (d->c == NULL) {
163 goto done;
166 rc = lp_wi_scan_global_parametrics("idmapconfig\\(.*\\):backend",
168 lp_scan_idmap_found_domain,
170 if (rc != 0) {
171 fprintf(stderr,
172 "FATAL: wi_scan_global_parametrics failed: %d",
173 rc);
176 /* Check autorid backend */
177 if (strequal(lp_idmap_default_backend(), "autorid")) {
178 struct idmap_config *c = NULL;
179 bool found = false;
181 for (i = 0; i < d->count; i++) {
182 c = &d->c[i];
184 if (strequal(c->backend, "autorid")) {
185 found = true;
186 break;
190 if (found) {
191 uint32_t rangesize =
192 idmap_config_int("*", "rangesize", 100000);
193 uint32_t maxranges =
194 (c->high - c->low + 1) / rangesize;
196 if (((c->high - c->low + 1) % rangesize) != 0) {
197 fprintf(stderr,
198 "WARNING: The idmap autorid range "
199 "[%u-%u] SHOULD be a multiple of "
200 "the rangesize [%u]!"
201 "\n\n",
202 c->low,
203 c->high,
204 rangesize);
207 if (maxranges < 2) {
208 fprintf(stderr,
209 "ERROR: The idmap autorid range "
210 "[%u-%u] needs to be at least twice as "
211 "big as the rangesize [%u]!"
212 "\n\n",
213 c->low,
214 c->high,
215 rangesize);
216 ok = false;
217 goto done;
222 /* Check for overlapping idmap ranges */
223 for (i = 0; i < d->count; i++) {
224 struct idmap_config *c = &d->c[i];
225 uint32_t j;
227 for (j = 0; j < d->count && j != i; j++) {
228 struct idmap_config *x = &d->c[j];
230 if ((c->low >= x->low && c->low <= x->high) ||
231 (c->high >= x->low && c->high <= x->high)) {
233 * Allow overlapping ranges for idmap_ad
234 * and idmap_nss
236 ok = strequal(c->backend, x->backend);
237 if (ok) {
238 ok = strequal(c->backend, "ad") ||
239 strequal(c->backend, "nss");
240 if (ok) {
241 fprintf(stderr,
242 "NOTE: The idmap_%s "
243 "range for the domain "
244 "%s overlaps with the "
245 "range of %s.\n\n",
246 c->backend,
247 c->domain_name,
248 x->domain_name);
249 continue;
253 fprintf(stderr,
254 "ERROR: The idmap range for the domain "
255 "%s (%s) overlaps with the range of "
256 "%s (%s)!\n\n",
257 c->domain_name,
258 c->backend,
259 x->domain_name,
260 x->backend);
261 ok = false;
262 goto done;
267 ok = true;
268 done:
269 TALLOC_FREE(d);
270 return ok;
273 /***********************************************
274 Here we do a set of 'hard coded' checks for bad
275 configuration settings.
276 ************************************************/
278 static int do_global_checks(void)
280 int ret = 0;
281 SMB_STRUCT_STAT st;
282 const char *socket_options;
283 const struct loadparm_substitution *lp_sub =
284 loadparm_s3_global_substitution();
286 fprintf(stderr, "\n");
288 if (lp_security() >= SEC_DOMAIN && !lp_encrypt_passwords()) {
289 fprintf(stderr, "ERROR: in 'security=domain' mode the "
290 "'encrypt passwords' parameter must always be "
291 "set to 'true'.\n\n");
292 ret = 1;
295 if (lp_security() == SEC_ADS) {
296 const char *workgroup = lp_workgroup();
297 const char *realm = lp_realm();
299 if (workgroup == NULL || strlen(workgroup) == 0) {
300 fprintf(stderr,
301 "ERROR: The 'security=ADS' mode requires "
302 "'workgroup' parameter to be set!\n\n ");
303 ret = 1;
306 if (realm == NULL || strlen(realm) == 0) {
307 fprintf(stderr,
308 "ERROR: The 'security=ADS' mode requires "
309 "'realm' parameter to be set!\n\n ");
310 ret = 1;
315 if (lp_we_are_a_wins_server() && lp_wins_server_list()) {
316 fprintf(stderr, "ERROR: both 'wins support = true' and "
317 "'wins server = <server list>' cannot be set in "
318 "the smb.conf file. nmbd will abort with this "
319 "setting.\n\n");
320 ret = 1;
323 if (strequal(lp_workgroup(), lp_netbios_name())) {
324 fprintf(stderr, "WARNING: 'workgroup' and 'netbios name' "
325 "must differ.\n\n");
328 if (lp_client_ipc_signing() == SMB_SIGNING_IF_REQUIRED
329 || lp_client_ipc_signing() == SMB_SIGNING_OFF) {
330 fprintf(stderr, "WARNING: The 'client ipc signing' value "
331 "%s SMB signing is not used when contacting a "
332 "domain controller or other server. "
333 "This setting is not recommended; please be "
334 "aware of the security implications when using "
335 "this configuration setting.\n\n",
336 lp_client_ipc_signing() == SMB_SIGNING_OFF ?
337 "ensures" : "may mean");
340 if (strlen(lp_netbios_name()) > 15) {
341 fprintf(stderr, "WARNING: The 'netbios name' is too long "
342 "(max. 15 chars).\n\n");
345 if (!directory_exist_stat(lp_lock_directory(), &st)) {
346 fprintf(stderr, "ERROR: lock directory %s does not exist\n\n",
347 lp_lock_directory());
348 ret = 1;
349 } else if ((st.st_ex_mode & 0777) != 0755) {
350 fprintf(stderr, "WARNING: lock directory %s should have "
351 "permissions 0755 for browsing to work\n\n",
352 lp_lock_directory());
355 if (!directory_exist_stat(lp_state_directory(), &st)) {
356 fprintf(stderr, "ERROR: state directory %s does not exist\n\n",
357 lp_state_directory());
358 ret = 1;
359 } else if ((st.st_ex_mode & 0777) != 0755) {
360 fprintf(stderr, "WARNING: state directory %s should have "
361 "permissions 0755 for browsing to work\n\n",
362 lp_state_directory());
365 if (!directory_exist_stat(lp_cache_directory(), &st)) {
366 fprintf(stderr, "ERROR: cache directory %s does not exist\n\n",
367 lp_cache_directory());
368 ret = 1;
369 } else if ((st.st_ex_mode & 0777) != 0755) {
370 fprintf(stderr, "WARNING: cache directory %s should have "
371 "permissions 0755 for browsing to work\n\n",
372 lp_cache_directory());
375 if (!directory_exist_stat(lp_pid_directory(), &st)) {
376 fprintf(stderr, "ERROR: pid directory %s does not exist\n\n",
377 lp_pid_directory());
378 ret = 1;
381 if (lp_passdb_expand_explicit()) {
382 fprintf(stderr, "WARNING: passdb expand explicit = yes is "
383 "deprecated\n\n");
387 * Socket options.
389 socket_options = lp_socket_options();
390 if (socket_options != NULL &&
391 (strstr(socket_options, "SO_SNDBUF") ||
392 strstr(socket_options, "SO_RCVBUF") ||
393 strstr(socket_options, "SO_SNDLOWAT") ||
394 strstr(socket_options, "SO_RCVLOWAT")))
396 fprintf(stderr,
397 "WARNING: socket options = %s\n"
398 "This warning is printed because you set one of the\n"
399 "following options: SO_SNDBUF, SO_RCVBUF, SO_SNDLOWAT,\n"
400 "SO_RCVLOWAT\n"
401 "Modern server operating systems are tuned for\n"
402 "high network performance in the majority of situations;\n"
403 "when you set 'socket options' you are overriding those\n"
404 "settings.\n"
405 "Linux in particular has an auto-tuning mechanism for\n"
406 "buffer sizes (SO_SNDBUF, SO_RCVBUF) that will be\n"
407 "disabled if you specify a socket buffer size. This can\n"
408 "potentially cripple your TCP/IP stack.\n\n"
409 "Getting the 'socket options' correct can make a big\n"
410 "difference to your performance, but getting them wrong\n"
411 "can degrade it by just as much. As with any other low\n"
412 "level setting, if you must make changes to it, make\n "
413 "small changes and test the effect before making any\n"
414 "large changes.\n\n",
415 socket_options);
419 * Password server sanity checks.
422 if((lp_security() >= SEC_DOMAIN) && !*lp_password_server()) {
423 const char *sec_setting;
424 if(lp_security() == SEC_DOMAIN)
425 sec_setting = "domain";
426 else if(lp_security() == SEC_ADS)
427 sec_setting = "ads";
428 else
429 sec_setting = "";
431 fprintf(stderr, "ERROR: The setting 'security=%s' requires the "
432 "'password server' parameter be set to the "
433 "default value * or a valid password server.\n\n",
434 sec_setting );
435 ret = 1;
438 if((lp_security() >= SEC_DOMAIN) && (strcmp(lp_password_server(), "*") != 0)) {
439 const char *sec_setting;
440 if(lp_security() == SEC_DOMAIN)
441 sec_setting = "domain";
442 else if(lp_security() == SEC_ADS)
443 sec_setting = "ads";
444 else
445 sec_setting = "";
447 fprintf(stderr, "WARNING: The setting 'security=%s' should NOT "
448 "be combined with the 'password server' "
449 "parameter.\n"
450 "(by default Samba will discover the correct DC "
451 "to contact automatically).\n\n",
452 sec_setting );
456 * Password chat sanity checks.
459 if(lp_security() == SEC_USER && lp_unix_password_sync()) {
462 * Check that we have a valid lp_passwd_program() if not using pam.
465 #ifdef WITH_PAM
466 if (!lp_pam_password_change()) {
467 #endif
469 if((lp_passwd_program(talloc_tos(), lp_sub) == NULL) ||
470 (strlen(lp_passwd_program(talloc_tos(), lp_sub)) == 0))
472 fprintf(stderr,
473 "ERROR: the 'unix password sync' "
474 "parameter is set and there is no valid "
475 "'passwd program' parameter.\n\n");
476 ret = 1;
477 } else {
478 const char *passwd_prog;
479 char *truncated_prog = NULL;
480 const char *p;
482 passwd_prog = lp_passwd_program(talloc_tos(), lp_sub);
483 p = passwd_prog;
484 next_token_talloc(talloc_tos(),
486 &truncated_prog, NULL);
487 if (truncated_prog && access(truncated_prog, F_OK) == -1) {
488 fprintf(stderr,
489 "ERROR: the 'unix password sync' "
490 "parameter is set and the "
491 "'passwd program' (%s) cannot be "
492 "executed (error was %s).\n\n",
493 truncated_prog,
494 strerror(errno));
495 ret = 1;
499 #ifdef WITH_PAM
501 #endif
503 if(lp_passwd_chat(talloc_tos(), lp_sub) == NULL) {
504 fprintf(stderr,
505 "ERROR: the 'unix password sync' parameter is "
506 "set and there is no valid 'passwd chat' "
507 "parameter.\n\n");
508 ret = 1;
511 if ((lp_passwd_program(talloc_tos(), lp_sub) != NULL) &&
512 (strlen(lp_passwd_program(talloc_tos(), lp_sub)) > 0))
514 /* check if there's a %u parameter present */
515 if(strstr_m(lp_passwd_program(talloc_tos(), lp_sub), "%u") == NULL) {
516 fprintf(stderr,
517 "ERROR: the 'passwd program' (%s) "
518 "requires a '%%u' parameter.\n\n",
519 lp_passwd_program(talloc_tos(), lp_sub));
520 ret = 1;
525 * Check that we have a valid script and that it hasn't
526 * been written to expect the old password.
529 if(lp_encrypt_passwords()) {
530 if(strstr_m( lp_passwd_chat(talloc_tos(), lp_sub), "%o")!=NULL) {
531 fprintf(stderr,
532 "ERROR: the 'passwd chat' script [%s] "
533 "expects to use the old plaintext "
534 "password via the %%o substitution. With "
535 "encrypted passwords this is not "
536 "possible.\n\n",
537 lp_passwd_chat(talloc_tos(), lp_sub) );
538 ret = 1;
543 if (strlen(lp_winbind_separator()) != 1) {
544 fprintf(stderr, "ERROR: the 'winbind separator' parameter must "
545 "be a single character.\n\n");
546 ret = 1;
549 if (*lp_winbind_separator() == '+') {
550 fprintf(stderr, "'winbind separator = +' might cause problems "
551 "with group membership.\n\n");
554 if (lp_algorithmic_rid_base() < BASE_RID) {
555 /* Try to prevent admin foot-shooting, we can't put algorithmic
556 rids below 1000, that's the 'well known RIDs' on NT */
557 fprintf(stderr, "'algorithmic rid base' must be equal to or "
558 "above %lu\n\n", BASE_RID);
561 if (lp_algorithmic_rid_base() & 1) {
562 fprintf(stderr, "'algorithmic rid base' must be even.\n\n");
565 if (lp_server_role() != ROLE_STANDALONE) {
566 const char *default_backends[] = {
567 "tdb", "tdb2", "ldap", "autorid", "hash"
569 const char *idmap_backend;
570 bool valid_backend = false;
571 uint32_t i;
572 bool ok;
574 idmap_backend = lp_idmap_default_backend();
576 for (i = 0; i < ARRAY_SIZE(default_backends); i++) {
577 ok = strequal(idmap_backend, default_backends[i]);
578 if (ok) {
579 valid_backend = true;
583 if (!valid_backend) {
584 ret = 1;
585 fprintf(stderr, "ERROR: Do not use the '%s' backend "
586 "as the default idmap backend!\n\n",
587 idmap_backend);
590 ok = do_idmap_check();
591 if (!ok) {
592 ret = 1;
596 #ifndef HAVE_DLOPEN
597 if (lp_preload_modules()) {
598 fprintf(stderr, "WARNING: 'preload modules = ' set while loading "
599 "plugins not supported.\n\n");
601 #endif
603 if (!lp_passdb_backend()) {
604 fprintf(stderr, "ERROR: passdb backend must have a value or be "
605 "left out\n\n");
608 if (lp_os_level() > 255) {
609 fprintf(stderr, "WARNING: Maximum value for 'os level' is "
610 "255!\n\n");
613 if (strequal(lp_dos_charset(), "UTF8") || strequal(lp_dos_charset(), "UTF-8")) {
614 fprintf(stderr, "ERROR: 'dos charset' must not be UTF8\n\n");
615 ret = 1;
618 if (lp_server_schannel() != true) { /* can be 'auto' */
619 fprintf(stderr,
620 "WARNING: You have not configured "
621 "'server schannel = yes' (the default). "
622 "Your server is vulnerable to \"ZeroLogon\" "
623 "(CVE-2020-1472)\n"
624 "If required use individual "
625 "'server require schannel:COMPUTERACCOUNT$ = no' "
626 "options\n\n");
628 if (lp_allow_nt4_crypto()) {
629 fprintf(stderr,
630 "WARNING: You have not configured "
631 "'allow nt4 crypto = no' (the default). "
632 "Your server is vulnerable to "
633 "CVE-2022-38023 and others!\n"
634 "If required use individual "
635 "'allow nt4 crypto:COMPUTERACCOUNT$ = yes' "
636 "options\n\n");
638 if (!lp_reject_md5_clients()) {
639 fprintf(stderr,
640 "WARNING: You have not configured "
641 "'reject md5 clients = yes' (the default). "
642 "Your server is vulnerable to "
643 "CVE-2022-38023!\n"
644 "If required use individual "
645 "'server reject md5 schannel:COMPUTERACCOUNT$ = yes' "
646 "options\n\n");
648 if (!lp_server_schannel_require_seal()) {
649 fprintf(stderr,
650 "WARNING: You have not configured "
651 "'server schannel require seal = yes' (the default). "
652 "Your server is vulnerable to "
653 "CVE-2022-38023!\n"
654 "If required use individual "
655 "'server schannel require seal:COMPUTERACCOUNT$ = no' "
656 "options\n\n");
659 if (lp_client_schannel() != true) { /* can be 'auto' */
660 fprintf(stderr,
661 "WARNING: You have not configured "
662 "'client schannel = yes' (the default). "
663 "Your server is vulnerable to \"ZeroLogon\" "
664 "(CVE-2020-1472)\n"
665 "If required use individual "
666 "'client schannel:NETBIOSDOMAIN = no' "
667 "options\n\n");
669 if (!lp_reject_md5_servers()) {
670 fprintf(stderr,
671 "WARNING: You have not configured "
672 "'reject md5 servers = yes' (the default). "
673 "Your server is vulnerable to "
674 "CVE-2022-38023\n"
675 "If required use individual "
676 "'reject md5 servers:NETBIOSDOMAIN = no' "
677 "options\n\n");
679 if (!lp_require_strong_key()) {
680 fprintf(stderr,
681 "WARNING: You have not configured "
682 "'require strong key = yes' (the default). "
683 "Your server is vulnerable to "
684 "CVE-2022-38023\n"
685 "If required use individual "
686 "'require strong key:NETBIOSDOMAIN = no' "
687 "options\n\n");
689 if (!lp_winbind_sealed_pipes()) {
690 fprintf(stderr,
691 "WARNING: You have not configured "
692 "'winbind sealed pipes = yes' (the default). "
693 "Your server is vulnerable to "
694 "CVE-2022-38023\n"
695 "If required use individual "
696 "'winbind sealed pipes:NETBIOSDOMAIN = no' "
697 "options\n\n");
700 if (lp_kerberos_encryption_types() == KERBEROS_ETYPES_LEGACY) {
701 fprintf(stderr,
702 "WARNING: You have configured "
703 "'kerberos encryption types = legacy'. "
704 "Your server is vulnerable to "
705 "CVE-2022-37966\n\n");
708 return ret;
712 * per-share logic tests
714 static void do_per_share_checks(int s)
716 const struct loadparm_substitution *lp_sub =
717 loadparm_s3_global_substitution();
718 const char **deny_list = lp_hosts_deny(s);
719 const char **allow_list = lp_hosts_allow(s);
720 const char **vfs_objects = NULL;
721 int i;
722 static bool uses_fruit;
723 static bool doesnt_use_fruit;
724 static bool fruit_mix_warned;
726 if(deny_list) {
727 for (i=0; deny_list[i]; i++) {
728 char *hasstar = strchr_m(deny_list[i], '*');
729 char *hasquery = strchr_m(deny_list[i], '?');
730 if(hasstar || hasquery) {
731 fprintf(stderr,
732 "Invalid character %c in hosts deny list "
733 "(%s) for service %s.\n\n",
734 hasstar ? *hasstar : *hasquery,
735 deny_list[i],
736 lp_servicename(talloc_tos(), lp_sub, s));
741 if(allow_list) {
742 for (i=0; allow_list[i]; i++) {
743 char *hasstar = strchr_m(allow_list[i], '*');
744 char *hasquery = strchr_m(allow_list[i], '?');
745 if(hasstar || hasquery) {
746 fprintf(stderr,
747 "Invalid character %c in hosts allow "
748 "list (%s) for service %s.\n\n",
749 hasstar ? *hasstar : *hasquery,
750 allow_list[i],
751 lp_servicename(talloc_tos(), lp_sub, s));
756 if(lp_level2_oplocks(s) && !lp_oplocks(s)) {
757 fprintf(stderr, "Invalid combination of parameters for service "
758 "%s. Level II oplocks can only be set if oplocks "
759 "are also set.\n\n",
760 lp_servicename(talloc_tos(), lp_sub, s));
763 if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
764 && !(lp_create_mask(s) & S_IXOTH))
766 fprintf(stderr,
767 "Invalid combination of parameters for service %s. Map "
768 "hidden can only work if create mask includes octal "
769 "01 (S_IXOTH).\n\n",
770 lp_servicename(talloc_tos(), lp_sub, s));
772 if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
773 && (lp_force_create_mode(s) & S_IXOTH))
775 fprintf(stderr,
776 "Invalid combination of parameters for service "
777 "%s. Map hidden can only work if force create mode "
778 "excludes octal 01 (S_IXOTH).\n\n",
779 lp_servicename(talloc_tos(), lp_sub, s));
781 if (!lp_store_dos_attributes(s) && lp_map_system(s)
782 && !(lp_create_mask(s) & S_IXGRP))
784 fprintf(stderr,
785 "Invalid combination of parameters for service "
786 "%s. Map system can only work if create mask includes "
787 "octal 010 (S_IXGRP).\n\n",
788 lp_servicename(talloc_tos(), lp_sub, s));
790 if (!lp_store_dos_attributes(s) && lp_map_system(s)
791 && (lp_force_create_mode(s) & S_IXGRP))
793 fprintf(stderr,
794 "Invalid combination of parameters for service "
795 "%s. Map system can only work if force create mode "
796 "excludes octal 010 (S_IXGRP).\n\n",
797 lp_servicename(talloc_tos(), lp_sub, s));
799 if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(s)) != '\0') {
800 fprintf(stderr,
801 "Warning: Service %s defines a print command, but "
802 "parameter is ignored when using CUPS libraries.\n\n",
803 lp_servicename(talloc_tos(), lp_sub, s));
806 vfs_objects = lp_vfs_objects(s);
807 if (vfs_objects && str_list_check(vfs_objects, "fruit")) {
808 uses_fruit = true;
809 } else {
810 doesnt_use_fruit = true;
813 if (uses_fruit && doesnt_use_fruit && !fruit_mix_warned) {
814 fruit_mix_warned = true;
815 fprintf(stderr,
816 "WARNING: some services use vfs_fruit, others don't. Mounting them "
817 "in conjunction on OS X clients results in undefined behaviour.\n\n");
821 int main(int argc, const char *argv[])
823 const char *config_file = NULL;
824 const struct loadparm_substitution *lp_sub =
825 loadparm_s3_global_substitution();
826 int opt;
827 int s;
828 static int silent_mode = False;
829 static int show_all_parameters = False;
830 int ret = 0;
831 poptContext pc;
832 static char *parameter_name = NULL;
833 static const char *section_name = NULL;
834 const char *cname;
835 const char *caddr;
836 static int show_defaults;
837 static int skip_logic_checks = 0;
838 bool ok;
840 struct poptOption long_options[] = {
841 POPT_AUTOHELP
843 .longName = "suppress-prompt",
844 .shortName = 's',
845 .argInfo = POPT_ARG_VAL,
846 .arg = &silent_mode,
847 .val = 1,
848 .descrip = "Suppress prompt for enter",
851 .longName = "verbose",
852 .shortName = 'v',
853 .argInfo = POPT_ARG_NONE,
854 .arg = &show_defaults,
855 .val = 1,
856 .descrip = "Show default options too",
859 .longName = "skip-logic-checks",
860 .shortName = 'l',
861 .argInfo = POPT_ARG_NONE,
862 .arg = &skip_logic_checks,
863 .val = 1,
864 .descrip = "Skip the global checks",
867 .longName = "show-all-parameters",
868 .shortName = '\0',
869 .argInfo = POPT_ARG_VAL,
870 .arg = &show_all_parameters,
871 .val = True,
872 .descrip = "Show the parameters, type, possible "
873 "values",
876 .longName = "parameter-name",
877 .shortName = '\0',
878 .argInfo = POPT_ARG_STRING,
879 .arg = &parameter_name,
880 .val = 0,
881 .descrip = "Limit testparm to a named parameter",
884 .longName = "section-name",
885 .shortName = '\0',
886 .argInfo = POPT_ARG_STRING,
887 .arg = &section_name,
888 .val = 0,
889 .descrip = "Limit testparm to a named section",
891 POPT_COMMON_DEBUG_ONLY
892 POPT_COMMON_OPTION_ONLY
893 POPT_COMMON_VERSION
894 POPT_TABLEEND
897 TALLOC_CTX *frame = talloc_stackframe();
898 struct loadparm_context *lp_ctx = NULL;
900 smb_init_locale();
902 ok = samba_cmdline_init(frame,
903 SAMBA_CMDLINE_CONFIG_NONE,
904 true /* require_smbconf */);
905 if (!ok) {
906 DBG_ERR("Failed to init cmdline parser!\n");
907 ret = 1;
908 goto done;
910 lp_ctx = samba_cmdline_get_lp_ctx();
913 * Set the default debug level to 1.
914 * Allow it to be overridden by the command line,
915 * not by smb.conf.
917 lpcfg_set_cmdline(lp_ctx, "log level", "1");
919 pc = samba_popt_get_context(getprogname(),
920 argc,
921 argv,
922 long_options,
924 if (pc == NULL) {
925 DBG_ERR("Failed to setup popt context!\n");
926 ret = 1;
927 goto done;
930 poptSetOtherOptionHelp(pc, "[OPTION...] <config-file> [host-name] [host-ip]");
932 while ((opt = poptGetNextOpt(pc)) != -1) {
933 switch (opt) {
934 case POPT_ERROR_BADOPT:
935 fprintf(stderr, "\nInvalid option %s: %s\n\n",
936 poptBadOption(pc, 0), poptStrerror(opt));
937 poptPrintUsage(pc, stderr, 0);
938 exit(1);
942 if (show_all_parameters) {
943 show_parameter_list();
944 exit(0);
947 if (poptPeekArg(pc)) {
948 config_file = talloc_strdup(frame, poptGetArg(pc));
949 if (config_file == NULL) {
950 DBG_ERR("out of memory\n");
951 TALLOC_FREE(frame);
952 exit(1);
954 } else {
955 config_file = get_dyn_CONFIGFILE();
958 cname = talloc_strdup(frame, poptGetArg(pc));
959 caddr = talloc_strdup(frame, poptGetArg(pc));
961 poptFreeContext(pc);
963 if ( cname && ! caddr ) {
964 printf ( "ERROR: You must specify both a machine name and an IP address.\n" );
965 ret = 1;
966 goto done;
969 fprintf(stderr,"Load smb config files from %s\n",config_file);
971 if (!lp_load_with_registry_shares(config_file)) {
972 fprintf(stderr,"Error loading services.\n");
973 ret = 1;
974 goto done;
977 fprintf(stderr,"Loaded services file OK.\n");
979 fprintf(stderr,
980 "Weak crypto is %sallowed by GnuTLS "
981 "(e.g. NTLM as a compatibility fallback)\n",
982 samba_gnutls_weak_crypto_allowed() ? "" : "dis");
984 if (skip_logic_checks == 0) {
985 ret = do_global_checks();
988 for (s=0;s<1000;s++) {
989 if (VALID_SNUM(s) && (skip_logic_checks == 0)) {
990 do_per_share_checks(s);
995 if (!section_name && !parameter_name) {
996 fprintf(stderr,
997 "Server role: %s\n\n",
998 server_role_str(lp_server_role()));
1001 if (!cname) {
1002 if (!silent_mode) {
1003 fprintf(stderr,"Press enter to see a dump of your service definitions\n");
1004 fflush(stdout);
1005 getc(stdin);
1007 if (parameter_name || section_name) {
1008 bool isGlobal = False;
1009 s = GLOBAL_SECTION_SNUM;
1011 if (!section_name) {
1012 section_name = GLOBAL_NAME;
1013 isGlobal = True;
1014 } else if ((isGlobal=!strwicmp(section_name, GLOBAL_NAME)) == 0 &&
1015 (s=lp_servicenumber(section_name)) == -1) {
1016 fprintf(stderr,"Unknown section %s\n",
1017 section_name);
1018 ret = 1;
1019 goto done;
1021 if (parameter_name) {
1022 if (!dump_a_parameter( s, parameter_name, stdout, isGlobal)) {
1023 fprintf(stderr,"Parameter %s unknown for section %s\n",
1024 parameter_name, section_name);
1025 ret = 1;
1026 goto done;
1028 } else {
1029 if (isGlobal == True)
1030 lp_dump(stdout, show_defaults, 0);
1031 else
1032 lp_dump_one(stdout, show_defaults, s);
1034 goto done;
1037 lp_dump(stdout, show_defaults, lp_numservices());
1040 if(cname && caddr){
1041 /* this is totally ugly, a real `quick' hack */
1042 for (s=0;s<1000;s++) {
1043 if (VALID_SNUM(s)) {
1044 if (allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1), cname, caddr)
1045 && allow_access(lp_hosts_deny(s), lp_hosts_allow(s), cname, caddr)) {
1046 fprintf(stderr,"Allow connection from %s (%s) to %s\n",
1047 cname,caddr,lp_servicename(talloc_tos(), lp_sub, s));
1048 } else {
1049 fprintf(stderr,"Deny connection from %s (%s) to %s\n",
1050 cname,caddr,lp_servicename(talloc_tos(), lp_sub, s));
1056 done:
1057 gfree_loadparm();
1058 TALLOC_FREE(frame);
1059 return ret;