int allow_access(const char *addr, const char **host_ptr, int i) { const char *allow_list = lp_hosts_allow(i); const char *deny_list = lp_hosts_deny(i); if (allow_list && !*allow_list) allow_list = NULL; if (deny_list && !*deny_list) deny_list = NULL; allow_forward_dns = lp_forward_lookup(i); /* If we match an allow-list item, we always allow access. */ if (allow_list) { if (access_match(allow_list, addr, host_ptr)) return 1; /* For an allow-list w/o a deny-list, disallow non-matches. */ if (!deny_list) return 0; } /* If we match a deny-list item (and got past any allow-list * items), we always disallow access. */ if (deny_list && access_match(deny_list, addr, host_ptr)) return 0; /* Allow all other access. */ return 1; }
static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address, const char *rhost, int snum, fstring dev) { char *raddr; raddr = tsocket_address_inet_addr_string(remote_address, talloc_tos()); if (raddr == NULL) { return NT_STATUS_NO_MEMORY; } if (!lp_snum_ok(snum) || !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum), rhost, raddr)) { return NT_STATUS_ACCESS_DENIED; } if (dev[0] == '?' || !dev[0]) { if (lp_printable(snum)) { fstrcpy(dev,"LPT1:"); } else if (strequal(lp_fstype(snum), "IPC")) { fstrcpy(dev, "IPC"); } else { fstrcpy(dev,"A:"); } } if (!strupper_m(dev)) { DEBUG(2,("strupper_m %s failed\n", dev)); return NT_STATUS_INVALID_PARAMETER; } if (lp_printable(snum)) { if (!strequal(dev, "LPT1:")) { return NT_STATUS_BAD_DEVICE_TYPE; } } else if (strequal(lp_fstype(snum), "IPC")) { if (!strequal(dev, "IPC")) { return NT_STATUS_BAD_DEVICE_TYPE; } } else if (!strequal(dev, "A:")) { return NT_STATUS_BAD_DEVICE_TYPE; } /* Behave as a printer if we are supposed to */ if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) { fstrcpy(dev, "LPT1:"); } return NT_STATUS_OK; }
int main(int argc, const char *argv[]) { const char *config_file = get_dyn_CONFIGFILE(); int s; static int silent_mode = False; static int show_all_parameters = False; int ret = 0; poptContext pc; static char *parameter_name = NULL; static const char *section_name = NULL; const char *cname; const char *caddr; static int show_defaults; static int skip_logic_checks = 0; struct poptOption long_options[] = { POPT_AUTOHELP {"suppress-prompt", 's', POPT_ARG_VAL, &silent_mode, 1, "Suppress prompt for enter"}, {"verbose", 'v', POPT_ARG_NONE, &show_defaults, 1, "Show default options too"}, {"skip-logic-checks", 'l', POPT_ARG_NONE, &skip_logic_checks, 1, "Skip the global checks"}, {"show-all-parameters", '\0', POPT_ARG_VAL, &show_all_parameters, True, "Show the parameters, type, possible values" }, {"parameter-name", '\0', POPT_ARG_STRING, ¶meter_name, 0, "Limit testparm to a named parameter" }, {"section-name", '\0', POPT_ARG_STRING, §ion_name, 0, "Limit testparm to a named section" }, POPT_COMMON_VERSION POPT_COMMON_DEBUGLEVEL POPT_COMMON_OPTION POPT_TABLEEND }; TALLOC_CTX *frame = talloc_stackframe(); load_case_tables(); /* * Set the default debug level to 2. * Allow it to be overridden by the command line, * not by smb.conf. */ lp_set_cmdline("log level", "2"); pc = poptGetContext(NULL, argc, argv, long_options, POPT_CONTEXT_KEEP_FIRST); poptSetOtherOptionHelp(pc, "[OPTION...] <config-file> [host-name] [host-ip]"); while(poptGetNextOpt(pc) != -1); if (show_all_parameters) { show_parameter_list(); exit(0); } setup_logging(poptGetArg(pc), DEBUG_STDERR); if (poptPeekArg(pc)) config_file = poptGetArg(pc); cname = poptGetArg(pc); caddr = poptGetArg(pc); poptFreeContext(pc); if ( cname && ! caddr ) { printf ( "ERROR: You must specify both a machine name and an IP address.\n" ); ret = 1; goto done; } fprintf(stderr,"Load smb config files from %s\n",config_file); if (!lp_load_with_registry_shares(config_file,False,True,False,True)) { fprintf(stderr,"Error loading services.\n"); ret = 1; goto done; } fprintf(stderr,"Loaded services file OK.\n"); if (skip_logic_checks == 0) { ret = do_global_checks(); } for (s=0;s<1000;s++) { if (VALID_SNUM(s)) if (strlen(lp_servicename(talloc_tos(), s)) > 12) { fprintf(stderr, "WARNING: You have some share names that are longer than 12 characters.\n" ); fprintf(stderr, "These may not be accessible to some older clients.\n" ); fprintf(stderr, "(Eg. Windows9x, WindowsMe, and smbclient prior to Samba 3.0.)\n" ); break; } } for (s=0;s<1000;s++) { if (VALID_SNUM(s) && (skip_logic_checks == 0)) { do_per_share_checks(s); } } if (!section_name && !parameter_name) { fprintf(stderr, "Server role: %s\n\n", server_role_str(lp_server_role())); } if (!cname) { if (!silent_mode) { fprintf(stderr,"Press enter to see a dump of your service definitions\n"); fflush(stdout); getc(stdin); } if (parameter_name || section_name) { bool isGlobal = False; s = GLOBAL_SECTION_SNUM; if (!section_name) { section_name = GLOBAL_NAME; isGlobal = True; } else if ((isGlobal=!strwicmp(section_name, GLOBAL_NAME)) == 0 && (s=lp_servicenumber(section_name)) == -1) { fprintf(stderr,"Unknown section %s\n", section_name); ret = 1; goto done; } if (parameter_name) { if (!dump_a_parameter( s, parameter_name, stdout, isGlobal)) { fprintf(stderr,"Parameter %s unknown for section %s\n", parameter_name, section_name); ret = 1; goto done; } } else { if (isGlobal == True) lp_dump(stdout, show_defaults, 0); else lp_dump_one(stdout, show_defaults, s); } goto done; } lp_dump(stdout, show_defaults, lp_numservices()); } if(cname && caddr){ /* this is totally ugly, a real `quick' hack */ for (s=0;s<1000;s++) { if (VALID_SNUM(s)) { if (allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1), cname, caddr) && allow_access(lp_hosts_deny(s), lp_hosts_allow(s), cname, caddr)) { fprintf(stderr,"Allow connection from %s (%s) to %s\n", cname,caddr,lp_servicename(talloc_tos(), s)); } else { fprintf(stderr,"Deny connection from %s (%s) to %s\n", cname,caddr,lp_servicename(talloc_tos(), s)); } } } } done: gfree_loadparm(); TALLOC_FREE(frame); return ret; }
/** * per-share logic tests */ static void do_per_share_checks(int s) { const char **deny_list = lp_hosts_deny(s); const char **allow_list = lp_hosts_allow(s); int i; if(deny_list) { for (i=0; deny_list[i]; i++) { char *hasstar = strchr_m(deny_list[i], '*'); char *hasquery = strchr_m(deny_list[i], '?'); if(hasstar || hasquery) { fprintf(stderr, "Invalid character %c in hosts deny list " "(%s) for service %s.\n\n", hasstar ? *hasstar : *hasquery, deny_list[i], lp_servicename(talloc_tos(), s)); } } } if(allow_list) { for (i=0; allow_list[i]; i++) { char *hasstar = strchr_m(allow_list[i], '*'); char *hasquery = strchr_m(allow_list[i], '?'); if(hasstar || hasquery) { fprintf(stderr, "Invalid character %c in hosts allow " "list (%s) for service %s.\n\n", hasstar ? *hasstar : *hasquery, allow_list[i], lp_servicename(talloc_tos(), s)); } } } if(lp_level2_oplocks(s) && !lp_oplocks(s)) { fprintf(stderr, "Invalid combination of parameters for service " "%s. Level II oplocks can only be set if oplocks " "are also set.\n\n", lp_servicename(talloc_tos(), s)); } if (!lp_store_dos_attributes(s) && lp_map_hidden(s) && !(lp_create_mask(s) & S_IXOTH)) { fprintf(stderr, "Invalid combination of parameters for service %s. Map " "hidden can only work if create mask includes octal " "01 (S_IXOTH).\n\n", lp_servicename(talloc_tos(), s)); } if (!lp_store_dos_attributes(s) && lp_map_hidden(s) && (lp_force_create_mode(s) & S_IXOTH)) { fprintf(stderr, "Invalid combination of parameters for service " "%s. Map hidden can only work if force create mode " "excludes octal 01 (S_IXOTH).\n\n", lp_servicename(talloc_tos(), s)); } if (!lp_store_dos_attributes(s) && lp_map_system(s) && !(lp_create_mask(s) & S_IXGRP)) { fprintf(stderr, "Invalid combination of parameters for service " "%s. Map system can only work if create mask includes " "octal 010 (S_IXGRP).\n\n", lp_servicename(talloc_tos(), s)); } if (!lp_store_dos_attributes(s) && lp_map_system(s) && (lp_force_create_mode(s) & S_IXGRP)) { fprintf(stderr, "Invalid combination of parameters for service " "%s. Map system can only work if force create mode " "excludes octal 010 (S_IXGRP).\n\n", lp_servicename(talloc_tos(), s)); } if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(talloc_tos(), s)) != '\0') { fprintf(stderr, "Warning: Service %s defines a print command, but " "parameter is ignored when using CUPS libraries.\n\n", lp_servicename(talloc_tos(), s)); } }
static int rsync_module(int fd, int i) { int argc=0; char *argv[MAX_ARGS]; char **argp; char line[MAXPATHLEN]; uid_t uid = (uid_t)-2; gid_t gid = (gid_t)-2; char *p; char *addr = client_addr(fd); char *host = client_name(fd); char *name = lp_name(i); int use_chroot = lp_use_chroot(i); int start_glob=0; int ret; char *request=NULL; extern int am_sender; extern int remote_version; extern int am_root; if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) { rprintf(FERROR,"rsync denied on module %s from %s (%s)\n", name, client_name(fd), client_addr(fd)); io_printf(fd,"@ERROR: access denied to %s from %s (%s)\n", name, client_name(fd), client_addr(fd)); return -1; } if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) { if (errno) { rprintf(FERROR,"failed to open lock file %s : %s\n", lp_lock_file(i), strerror(errno)); io_printf(fd,"@ERROR: failed to open lock file %s : %s\n", lp_lock_file(i), strerror(errno)); } else { rprintf(FERROR,"max connections (%d) reached\n", lp_max_connections(i)); io_printf(fd,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections(i)); } return -1; } auth_user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD "); if (!auth_user) { rprintf(FERROR,"auth failed on module %s from %s (%s)\n", name, client_name(fd), client_addr(fd)); io_printf(fd,"@ERROR: auth failed on module %s\n",name); return -1; } module_id = i; if (lp_read_only(i)) read_only = 1; am_root = (getuid() == 0); if (am_root) { p = lp_uid(i); if (!name_to_uid(p, &uid)) { if (!isdigit(*p)) { rprintf(FERROR,"Invalid uid %s\n", p); io_printf(fd,"@ERROR: invalid uid\n"); return -1; } uid = atoi(p); } p = lp_gid(i); if (!name_to_gid(p, &gid)) { if (!isdigit(*p)) { rprintf(FERROR,"Invalid gid %s\n", p); io_printf(fd,"@ERROR: invalid gid\n"); return -1; } gid = atoi(p); } } p = lp_include_from(i); add_exclude_file(p, 1, 1); p = lp_include(i); add_include_line(p); p = lp_exclude_from(i); add_exclude_file(p, 1, 0); p = lp_exclude(i); add_exclude_line(p); log_open(); if (use_chroot) { if (chroot(lp_path(i))) { rprintf(FERROR,"chroot %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chroot failed\n"); return -1; } if (!push_dir("/", 0)) { rprintf(FERROR,"chdir %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chdir failed\n"); return -1; } } else { if (!push_dir(lp_path(i), 0)) { rprintf(FERROR,"chdir %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chdir failed\n"); return -1; } } if (am_root) { if (setgid(gid)) { rprintf(FERROR,"setgid %d failed\n", gid); io_printf(fd,"@ERROR: setgid failed\n"); return -1; } if (setuid(uid)) { rprintf(FERROR,"setuid %d failed\n", uid); io_printf(fd,"@ERROR: setuid failed\n"); return -1; } am_root = (getuid() == 0); } io_printf(fd,"@RSYNCD: OK\n"); argv[argc++] = "rsyncd"; while (1) { if (!read_line(fd, line, sizeof(line)-1)) { return -1; } if (!*line) break; p = line; argv[argc] = strdup(p); if (!argv[argc]) { return -1; } if (start_glob) { if (start_glob == 1) { request = strdup(p); start_glob++; } glob_expand(name, argv, &argc, MAX_ARGS, !use_chroot); } else { argc++; } if (strcmp(line,".") == 0) { start_glob = 1; } if (argc == MAX_ARGS) { return -1; } } if (!use_chroot) { /* * Note that this is applied to all parameters, whether or not * they are filenames, but no other legal parameters contain * the forms that need to be sanitized so it doesn't hurt; * it is not known at this point which parameters are files * and which aren't. */ for (i = 1; i < argc; i++) { sanitize_path(argv[i]); } } ret = parse_arguments(argc, argv, 0); if (request) { if (*auth_user) { rprintf(FINFO,"rsync %s %s from %s@%s (%s)\n", am_sender?"on":"to", request, auth_user, host, addr); } else { rprintf(FINFO,"rsync %s %s from %s (%s)\n", am_sender?"on":"to", request, host, addr); } free(request); } #if !TRIDGE /* don't allow the logs to be flooded too fast */ if (verbose > 1) verbose = 1; #endif argc -= optind; argp = argv + optind; optind = 0; if (remote_version > 17 && am_sender) io_start_multiplex_out(fd); if (!ret) { option_error(); } if (lp_timeout(i)) { extern int io_timeout; io_timeout = lp_timeout(i); } start_server(fd, fd, argc, argp); return 0; }
/** * per-share logic tests */ static void do_per_share_checks(int s) { const char **deny_list = lp_hosts_deny(s); const char **allow_list = lp_hosts_allow(s); const char **vfs_objects = NULL; int i; static bool uses_fruit; static bool doesnt_use_fruit; static bool fruit_mix_warned; if(deny_list) { for (i=0; deny_list[i]; i++) { char *hasstar = strchr_m(deny_list[i], '*'); char *hasquery = strchr_m(deny_list[i], '?'); if(hasstar || hasquery) { fprintf(stderr, "Invalid character %c in hosts deny list " "(%s) for service %s.\n\n", hasstar ? *hasstar : *hasquery, deny_list[i], lp_servicename(talloc_tos(), s)); } } } if(allow_list) { for (i=0; allow_list[i]; i++) { char *hasstar = strchr_m(allow_list[i], '*'); char *hasquery = strchr_m(allow_list[i], '?'); if(hasstar || hasquery) { fprintf(stderr, "Invalid character %c in hosts allow " "list (%s) for service %s.\n\n", hasstar ? *hasstar : *hasquery, allow_list[i], lp_servicename(talloc_tos(), s)); } } } if(lp_level2_oplocks(s) && !lp_oplocks(s)) { fprintf(stderr, "Invalid combination of parameters for service " "%s. Level II oplocks can only be set if oplocks " "are also set.\n\n", lp_servicename(talloc_tos(), s)); } if (!lp_store_dos_attributes(s) && lp_map_hidden(s) && !(lp_create_mask(s) & S_IXOTH)) { fprintf(stderr, "Invalid combination of parameters for service %s. Map " "hidden can only work if create mask includes octal " "01 (S_IXOTH).\n\n", lp_servicename(talloc_tos(), s)); } if (!lp_store_dos_attributes(s) && lp_map_hidden(s) && (lp_force_create_mode(s) & S_IXOTH)) { fprintf(stderr, "Invalid combination of parameters for service " "%s. Map hidden can only work if force create mode " "excludes octal 01 (S_IXOTH).\n\n", lp_servicename(talloc_tos(), s)); } if (!lp_store_dos_attributes(s) && lp_map_system(s) && !(lp_create_mask(s) & S_IXGRP)) { fprintf(stderr, "Invalid combination of parameters for service " "%s. Map system can only work if create mask includes " "octal 010 (S_IXGRP).\n\n", lp_servicename(talloc_tos(), s)); } if (!lp_store_dos_attributes(s) && lp_map_system(s) && (lp_force_create_mode(s) & S_IXGRP)) { fprintf(stderr, "Invalid combination of parameters for service " "%s. Map system can only work if force create mode " "excludes octal 010 (S_IXGRP).\n\n", lp_servicename(talloc_tos(), s)); } if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(talloc_tos(), s)) != '\0') { fprintf(stderr, "Warning: Service %s defines a print command, but " "parameter is ignored when using CUPS libraries.\n\n", lp_servicename(talloc_tos(), s)); } vfs_objects = lp_vfs_objects(s); if (vfs_objects && str_list_check(vfs_objects, "fruit")) { uses_fruit = true; if (!lp_ea_support(s) && !lp_ea_support(-1)) { fprintf(stderr, "ERROR: Service \"%s\" uses vfs_fruit, but " "that requires \"ea support = yes\".\n\n", lp_servicename(talloc_tos(), s)); } } else { doesnt_use_fruit = true; } if (uses_fruit && doesnt_use_fruit && !fruit_mix_warned) { fruit_mix_warned = true; fprintf(stderr, "WARNING: some services use vfs_fruit, others don't. Mounting them " "in conjunction on OS X clients results in undefined behaviour.\n\n"); } }