def smbInfoSave(self, options): """ Set information in global section: @param options: dict with global options """ current = self.getSmbInfo() # Don't write an empty value # Use the SAMBA default for option in ["logon home", "logon drive"]: if options[option] == "": self.remove("global", option) del options[option] # We update only what has changed from the current configuration for option in self.supportedGlobalOptions: try: if option in options: options[option] = self.mapOptionValue(options[option]) if options[option] != current[option]: self.setContent("global", option, options[option]) # else do nothing, the option is already set else: self.remove("global", option) except KeyError: # Just ignore the option if it was not sent pass if current["pdc"] != options['pdc']: if options['pdc']: self.setContent('global', 'domain logons', 'yes') self.setContent('global', 'domain master', 'yes') self.setContent('global', 'os level', '255') else: self.setContent('global', 'domain logons', 'no') self.remove('global', 'domain master') self.remove('global', 'os level') if options['hashomes']: self.setContent('homes', 'comment', 'User shares') self.setContent('homes', 'browseable', 'no') self.setContent('homes', 'read only', 'no') self.setContent('homes', 'create mask', '0700') self.setContent('homes', 'directory mask', '0700') # Set the vscan-av plugin if available if os.path.exists(SambaConfig("samba").av_so): self.setContent("homes", "vfs objects", os.path.splitext(os.path.basename(SambaConfig("samba").av_so))[0]) elif 'homes' in self.config: del self.config["homes"] self.setContent('global', 'logon home', '') # Disable global profiles if not options['hasprofiles']: self.setContent('global', 'logon path', '') # Save file self.save() return 0
def modShare(name, path, comment, perms, admingroups, recursive=True, browseable=True, av=0, customparameters=None): smbObj = SambaConf(SambaConfig("samba").samba_conf_file) smbObj.addShare(name, path, comment, perms, admingroups, recursive, browseable, av, customparameters, True) smbObj.save()
def backupShare(share, media, login): """ Launch as a background process the backup of a share """ r = AF().log(PLUGIN_NAME, AA.SAMBA_BACKUP_SHARE, [(share, AT.SHARE), (login, AT.USER)], media) config = BasePluginConfig("base") cmd = os.path.join(config.backuptools, "backup.sh") if share == "homes": # FIXME: Maybe we should have a configuration directive to tell that # all users home are stored into /home savedir = "/home/" else: smbObj = SambaConf(SambaConfig("samba").samba_conf_file) savedir = smbObj.getContent(share, "path") # Run backup process in background shlaunchBackground( cmd + " " + share + " " + savedir + " " + config.backupdir + " " + login + " " + media + " " + config.backuptools, "backup share " + share, progressBackup) r.commit() return os.path.join(config.backupdir, "%s-%s-%s" % (login, share, strftime("%Y%m%d")))
def __init__(self, smbconffile="/etc/samba/smb.conf", conffile=None, conffilebase=None): """ Constructor for object that read/write samba conf file. We use the testparm command on the smb configuration file to sanitize it, and to replace all keyword synonyms with the preferred keywords: - 'write ok', 'writeable', 'writable' -> 'read only' - 'public' -> 'guest ok' ... In SAMBA source code, parameters are defined in param/loadparm.c """ config = SambaConfig("samba", conffile) self.defaultSharesPath = config.defaultSharesPath self.authorizedSharePaths = config.authorizedSharePaths self.conffilebase = conffilebase self.smbConfFile = smbconffile # Parse SAMBA configuration file try: self.config = ConfigObj(self.smbConfFile, interpolation=False, list_values=False, write_empty_values=True, encoding='utf8') except ParseError, e: logger.error("Failed to parse %s : %s " % (self.smbConfFile, e))
def shareCustomParameters(name): """get an array of additionnal params about a share""" smbObj = SambaConf(SambaConfig("samba").samba_conf_file) return smbObj.shareCustomParameters(name)
def shareInfo(name): """get an array of information about a share""" smbObj = SambaConf(SambaConfig("samba").samba_conf_file) return smbObj.shareInfo(name)
def delShare(name, file): smbObj = SambaConf(SambaConfig("samba").samba_conf_file) smbObj.delShare(name, file) smbObj.save() return 0
for root, dirs, files in os.walk(path): acls.applyto(root) acls.applyto(root, posix1e.ACL_TYPE_DEFAULT) for file in map(lambda f: os.path.join(root, f), files): acls.applyto(file) else: logger.error("Cannot save ACL on folder " + path) tmpInsert['valid users'] = ', '.join(map(sanitize_name, reduce(operator.add, [j for p, j in perms.items()], []))) tmpInsert['write list'] = ', '.join(map(sanitize_name, reduce(operator.add, [j for p, j in perms.items() if 'w' in p], []))) # Set the anti-virus plugin if available if av: tmpInsert['vfs objects'] = os.path.splitext(os.path.basename(SambaConfig("samba").av_so))[0] # Set the admin groups for the share if admingroups: # need to add '@' admingroups = map(lambda g: '@' + g, admingroups) tmpInsert["admin users"] = ", ".join(map(sanitize_name, admingroups)) # include admin users in valid users list and write list if tmpInsert['writeable'] == 'no': tmpInsert['valid users'] = ', '.join(filter(bool, [tmpInsert['valid users'], tmpInsert["admin users"]])) tmpInsert['write list'] = ', '.join(filter(bool, [tmpInsert['write list'], tmpInsert["admin users"]])) self.config[name] = tmpInsert info = self.shareInfo(name) if mod:
def reloadSamba(): r = AF().log(PLUGIN_NAME, AA.SAMBA_RELOAD_SAMBA) shlaunchBackground(SambaConfig("samba").samba_init_script + ' reload') r.commit() return 0
def isPdc(): try: smbObj = SambaConf(SambaConfig("samba").samba_conf_file) except: raise Exception("Can't open SAMBA configuration file") return smbObj.isPdc()
def getDetailedShares(filter="", start=0, end=None): """Get a complete array of information about all shares""" smbObj = SambaConf(SambaConfig("samba").samba_conf_file) resList = smbObj.getDetailedShares(filter, start, end) return resList
def getDefaultSharesPath(): """ @return: the default SAMBA share path @rtype: str """ return SambaConfig("samba").defaultSharesPath
def isAuthorizedSharePath(path): return SambaConf( SambaConfig("samba").samba_conf_file).isAuthorizedSharePath(path)
def isSmbAntiVirus(): return os.path.exists(SambaConfig("samba").av_so)
def __init__(self, conffile = None, conffilebase = None): ldapUserGroupControl.__init__(self, conffilebase) self.configSamba = SambaConfig("samba") self.baseComputersDN = self.configSamba.baseComputersDN self.hooks.update(self.configSamba.hooks)
def getSmbInfo(): """get main information of global section""" smbObj = SambaConf(SambaConfig("samba").samba_conf_file) return smbObj.getSmbInfo()
def smbInfoSave(options): """save information about global section""" smbObj = SambaConf(SambaConfig("samba").samba_conf_file) return smbObj.smbInfoSave(options)
def getACLOnShare(name): smbObj = SambaConf(SambaConfig("samba").samba_conf_file) return smbObj.getACLOnShare(name)
def isProfiles(): """ check if global profiles are setup """ smbObj = SambaConf(SambaConfig("samba").samba_conf_file) return smbObj.isProfiles()
def getAdminUsersOnShare(name): return SambaConf( SambaConfig("samba").samba_conf_file).getAdminUsersOnShare(name)
def restartSamba(): r = AF().log(PLUGIN_NAME, AA.SAMBA_RESTART_SAMBA) shlaunchBackground(SambaConfig("samba").samba_init_script + ' restart') r.commit() return 0
def isBrowseable(name): return SambaConf(SambaConfig("samba").samba_conf_file).isBrowseable(name)
def activate(): """ this function define if the module "base" can be activated. @return: return True if this module can be activate @rtype: boolean """ config = SambaConfig("samba") if config.disabled: logger.info("samba plugin disabled by configuration.") return False if config.defaultSharesPath: if config.defaultSharesPath.endswith("/"): logger.error("Trailing / is not allowed in defaultSharesPath") return False if not os.path.exists(config.defaultSharesPath): logger.error("The default shares path '%s' does not exist" % config.defaultSharesPath) return False for cpath in config.authorizedSharePaths: if cpath.endswith("/"): logger.error("Trailing / is not allowed in authorizedSharePaths") return False if not os.path.exists(cpath): logger.error("The authorized share path '%s' does not exist" % cpath) return False # Verify if samba conf file exist conf = config.samba_conf_file if not os.path.exists(conf): logger.error(conf + " does not exist") return False # validate smb.conf smbconf = SambaConf() if not smbconf.validate(conf): logger.error("SAMBA configuration file is not valid") return False # For each share, test if it sharePath exists for share in getDetailedShares(): shareName = share[0] infos = shareInfo(shareName) if infos: sharePath = infos['sharePath'] if sharePath and not '%' in sharePath and not os.path.exists( sharePath): # only show error logger.error("The samba share path '%s' does not exist." % sharePath) else: return False try: ldapObj = ldapUserGroupControl() except ldap.INVALID_CREDENTIALS: logger.error("Can't bind to LDAP: invalid credentials.") return False # Test if the Samba LDAP schema is available in the directory try: schema = ldapObj.getSchema("sambaSamAccount") if len(schema) <= 0: logger.error("Samba schema is not included in LDAP directory") return False except: logger.exception("invalid schema") return False # Verify if init script exist init = config.samba_init_script if not os.path.exists(init): logger.error(init + " does not exist") return False # If SAMBA is defined as a PDC, make extra checks if smbconf.isPdc(): samba = SambaLDAP() # Create SAMBA computers account OU if it doesn't exist head, path = samba.baseComputersDN.split(",", 1) ouName = head.split("=")[1] samba.addOu(ouName, path) # Check that a sambaDomainName entry is in LDAP directory domainInfos = samba.getDomain() # Set domain policy samba.setDomainPolicy() if not domainInfos: logger.error( "Can't find sambaDomainName entry in LDAP for domain %s. Please check your SAMBA LDAP configuration." % smbconf.getContent("global", "workgroup")) return False smbconfbasesuffix = smbconf.getContent("global", "ldap suffix") if not smbconfbasesuffix: logger.error("SAMBA 'ldap suffix' option is not setted.") return False if ldap.explode_dn(samba.baseDN) != ldap.explode_dn(smbconfbasesuffix): logger.error( "SAMBA 'ldap suffix' option is not equal to MMC 'baseDN' option." ) return False # Check that SAMBA and MMC given OU are in sync for option in [ ("ldap user suffix", "baseUsersDN", samba.baseUsersDN), ("ldap group suffix", "baseGroupsDN", samba.baseGroupsDN), ("ldap machine suffix", "baseComputersDN", samba.baseComputersDN) ]: smbconfsuffix = smbconf.getContent("global", option[0]) if not smbconfsuffix: logger.error("SAMBA '" + option[0] + "' option is not setted") return False # Do a case insensitive comparison of the corresponding MMC / SAMBA options if ldap.explode_rdn(smbconfsuffix)[0].lower() != ldap.explode_rdn( option[2])[0].lower(): logger.error("SAMBA option '" + option[0] + "' is not equal to MMC '" + option[1] + "' option.") return False # Check that "ldap delete dn" SAMBA option is set to "No" smbconfdeletedn = smbconf.isValueTrue( smbconf.getContent("global", "ldap delete dn")) if smbconfdeletedn == 1: logger.error("SAMBA option 'ldap delete dn' must be disabled.") return False # Check that Domain Computers group exists # We need it to put a machine account in the right group when joigning it to the domain if not samba.getDomainComputersGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Computers' group. Please check your SAMBA LDAP configuration." ) return False # Check that Domain Admins group exists if not samba.getDomainAdminsGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Admins' group. Please check your SAMBA LDAP configuration." ) return False # Check that Domain Guests group exists if not samba.getDomainGuestsGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Guests' group. Please check your SAMBA LDAP configuration." ) return False # Check that Domain Users group exists if not samba.getDomainUsersGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Users' group. Please check your SAMBA LDAP configuration." ) return False # Check that add machine script option is set, and that the given script exist addMachineScript = smbconf.getContent("global", "add machine script") if not addMachineScript: logger.error("SAMBA 'add machine script' option is not set.") return False else: script = addMachineScript.split(" ")[0] if not os.path.exists(script): logger.error( "SAMBA 'add machine script' option is set to a non existing file: " + script) return False # Issue a warning if NSCD is running if os.path.exists("/var/run/nscd.pid") or os.path.exists( "/var/run/.nscd_socket") or os.path.exists("/var/run/nscd"): logger.warning( "Looks like NSCD is installed on your system. You should not run NSCD on a SAMBA server." ) # Check that os level is set to 255 oslevel = smbconf.getContent("global", "os level") if int(oslevel) < 255: logger.debug("Set SAMBA os level to 255.") smbconf.setContent("global", "os level", "255") smbconf.save() reloadSamba() try: from mmc.plugins.dashboard.manager import DashboardManager from mmc.plugins.samba.panel import SambaPanel DM = DashboardManager() DM.register_panel(SambaPanel("samba")) except ImportError: pass return True
def getDetailedShares(): """Get a complete array of information about all shares""" smbObj = SambaConf(SambaConfig("samba").samba_conf_file) resList = smbObj.getDetailedShares() return resList