/* Unix SMB/CIFS implementation. service (connection) opening and closing Copyright (C) Andrew Tridgell 1992-1998 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "includes.h" #include "system/filesys.h" #include "../lib/tsocket/tsocket.h" #include "smbd/smbd.h" #include "smbd/globals.h" #include "../librpc/gen_ndr/netlogon.h" #include "../libcli/security/security.h" #include "printing/pcap.h" #include "printing/printer_list.h" #include "passdb/lookup_sid.h" #include "auth.h" #include "lib/param/loadparm.h" static int load_registry_service(const char *servicename) { if (!lp_registry_shares()) { return -1; } if ((servicename == NULL) || (*servicename == '\0')) { return -1; } if (strequal(servicename, GLOBAL_NAME)) { return -2; } if (!process_registry_service(servicename)) { return -1; } return lp_servicenumber(servicename); } void load_registry_shares(void) { DEBUG(8, ("load_registry_shares()\n")); if (!lp_registry_shares()) { return; } process_registry_shares(); return; } /**************************************************************************** Add a home service. Returns the new service number or -1 if fail. ****************************************************************************/ int add_home_service(const char *service, const char *username, const char *homedir) { int iHomeService; if (!service || !homedir || homedir[0] == '\0') return -1; if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) { if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) { return -1; } } /* * If this is a winbindd provided username, remove * the domain component before adding the service. * Log a warning if the "path=" parameter does not * include any macros. */ { const char *p = strchr(service,*lp_winbind_separator()); /* We only want the 'user' part of the string */ if (p) { service = p + 1; } } if (!lp_add_home(service, iHomeService, username, homedir)) { return -1; } return lp_servicenumber(service); } /** * Find a service entry. * * @param service is modified (to canonical form??) **/ int find_service(TALLOC_CTX *ctx, const char *service_in, char **p_service_out) { const struct loadparm_substitution *lp_sub = loadparm_s3_global_substitution(); int iService; if (!service_in) { return -1; } /* First make a copy. */ *p_service_out = talloc_strdup(ctx, service_in); if (!*p_service_out) { return -1; } all_string_sub(*p_service_out,"\\","/",0); iService = lp_servicenumber(*p_service_out); /* * check for whether the service is a registry share before * handling home directories. This is to ensure that * that in the case service name is identical to a user's * home directory, the explicit service is preferred. */ if (iService < 0) { iService = load_registry_service(*p_service_out); } /* now handle the special case of a home directory */ if (iService < 0) { char *phome_dir = get_user_home_dir(ctx, *p_service_out); if(!phome_dir) { /* * Try mapping the servicename, it may * be a Windows to unix mapped user name. */ if(map_username(ctx, *p_service_out, p_service_out)) { if (*p_service_out == NULL) { /* Out of memory. */ return -1; } phome_dir = get_user_home_dir( ctx, *p_service_out); } } DEBUG(3,("checking for home directory %s gave %s\n",*p_service_out, phome_dir?phome_dir:"(NULL)")); if (!strequal(phome_dir, "/")) { iService = add_home_service(*p_service_out, *p_service_out, /* username */ phome_dir); } } /* If we still don't have a service, attempt to add it as a printer. */ if (iService < 0) { int iPrinterService; if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) { iPrinterService = load_registry_service(PRINTERS_NAME); } if (iPrinterService >= 0) { DEBUG(3,("checking whether %s is a valid printer name...\n", *p_service_out)); if (printer_list_printername_exists(*p_service_out)) { DEBUG(3,("%s is a valid printer name\n", *p_service_out)); DEBUG(3,("adding %s as a printer service\n", *p_service_out)); lp_add_printer(*p_service_out, iPrinterService); iService = lp_servicenumber(*p_service_out); if (iService < 0) { DEBUG(0,("failed to add %s as a printer service!\n", *p_service_out)); } } else { DEBUG(3,("%s is not a valid printer name\n", *p_service_out)); } } } /* Is it a usershare service ? */ if (iService < 0 && *lp_usershare_path(talloc_tos(), lp_sub)) { /* Ensure the name is canonicalized. */ if (!strlower_m(*p_service_out)) { goto fail; } iService = load_usershare_service(*p_service_out); } /* just possibly it's a default service? */ if (iService < 0) { char *pdefservice = lp_defaultservice(talloc_tos(), lp_sub); if (pdefservice && *pdefservice && !strequal(pdefservice, *p_service_out) && !strstr_m(*p_service_out,"..")) { /* * We need to do a local copy here as lp_defaultservice() * returns one of the rotating lp_string buffers that * could get overwritten by the recursive find_service() call * below. Fix from Josef Hinteregger . */ char *defservice = talloc_strdup(ctx, pdefservice); if (!defservice) { goto fail; } /* Disallow anything except explicit share names. */ if (strequal(defservice,HOMES_NAME) || strequal(defservice, PRINTERS_NAME) || strequal(defservice, "IPC$")) { TALLOC_FREE(defservice); goto fail; } iService = find_service(ctx, defservice, p_service_out); if (!*p_service_out) { TALLOC_FREE(defservice); iService = -1; goto fail; } if (iService >= 0) { all_string_sub(*p_service_out, "_","/",0); iService = lp_add_service(*p_service_out, iService); } TALLOC_FREE(defservice); } } if (iService >= 0) { if (!VALID_SNUM(iService)) { DEBUG(0,("Invalid snum %d for %s\n",iService, *p_service_out)); iService = -1; } } fail: if (iService < 0) { DEBUG(3,("find_service() failed to find service %s\n", *p_service_out)); } return (iService); } bool lp_allow_local_address( int snum, const struct tsocket_address *local_address) { bool is_inet = tsocket_address_is_inet(local_address, "ip"); const char **server_addresses = lp_server_addresses(snum); char *local = NULL; ssize_t i; if (!is_inet) { return false; } if (server_addresses == NULL) { return true; } local = tsocket_address_inet_addr_string(local_address, talloc_tos()); if (local == NULL) { return false; } for (i=0; server_addresses[i] != NULL; i++) { struct tsocket_address *server_addr = NULL; char *server_addr_string = NULL; bool equal; int ret; /* * Go through struct tsocket_address to normalize the * string representation */ ret = tsocket_address_inet_from_strings( talloc_tos(), "ip", server_addresses[i], 0, &server_addr); if (ret == -1) { DBG_WARNING("tsocket_address_inet_from_strings " "failed for %s: %s, ignoring\n", server_addresses[i], strerror(errno)); continue; } server_addr_string = tsocket_address_inet_addr_string( server_addr, talloc_tos()); TALLOC_FREE(server_addr); if (server_addr_string == NULL) { DBG_ERR("tsocket_address_inet_addr_string failed " "for %s, ignoring\n", server_addresses[i]); continue; } equal = strequal(local, server_addr_string); TALLOC_FREE(server_addr_string); if (equal) { TALLOC_FREE(local); return true; } } TALLOC_FREE(local); return false; }