def _getInstalledPrintersOfUser(username):
    logging.info(f"Getting installed printers of {username}")
    command = f"lpstat -U {username} -p"
    #logging.debug("running '{}'".format(command))

    result = subprocess.run(command,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            universal_newlines=True,
                            shell=True)

    if not result.returncode == 0:
        logging.info("No Printers installed.")
        return True, []

    rawInstalledPrinters = list(filter(None, result.stdout.split("\n")))
    installedPrinters = []

    for rawInstalledPrinter in rawInstalledPrinters:
        rawInstalledPrinterList = list(
            filter(None, rawInstalledPrinter.split(" ")))

        if len(rawInstalledPrinterList) < 2:
            continue

        installedPrinter = rawInstalledPrinterList[1]
        installedPrinters.append(installedPrinter)

    return True, installedPrinters
Esempio n. 2
0
def writeNetworkConfig(newNetworkConfig):
    """
    Write the network configuration in `/etc/linuxmuster-linuxclient7/network.conf`

    :param newNetworkConfig: The new config
    :type newNetworkConfig: dict
    :return: True or False
    :rtype: bool
    """
    networkConfig = configparser.ConfigParser(interpolation=None)

    try:
        networkConfig["network"] = {}
        networkConfig["network"]["version"] = str(_networkConfigVersion())
        networkConfig["network"]["serverHostname"] = newNetworkConfig[
            "serverHostname"]
        networkConfig["network"]["domain"] = newNetworkConfig["domain"]
        networkConfig["network"]["realm"] = newNetworkConfig["realm"]
    except Exception as e:
        logging.error("Error when preprocessing new network configuration!")
        logging.exception(e)
        return False

    try:
        logging.info("Writing new network Configuration")
        with open(constants.networkConfigFilePath, 'w') as networkConfigFile:
            networkConfig.write(networkConfigFile)

    except Exception as e:
        logging.error("Failed!")
        logging.exception(e)
        return False

    return True
Esempio n. 3
0
def _cleanOldDomainJoins():
    # stop sssd
    logging.info("Stopping sssd")
    if subprocess.call(["service", "sssd", "stop"]) != 0:
        logging.error("Failed!")
        return False

    # Clean old domain join data
    logging.info("Deleting old kerberos tickets.")
    subprocess.call(["kdestroy"],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)

    if not realm.leaveAll():
        return False

    # delete krb5.keytab file, if existent
    logging.info('Deleting krb5.keytab if it exists ... ')
    if not fileHelper.deleteFile("/etc/krb5.keytab"):
        return False

    # delete old CA Certificate
    logging.info('Deleting old CA certificate if it exists ... ')
    if not fileHelper.deleteFilesWithExtension("/var/lib/samba/private/tls",
                                               ".pem"):
        return False

    # remove network.conf
    logging.info(f"Deleting {constants.networkConfigFilePath} if exists ...")
    if not fileHelper.deleteFile(constants.networkConfigFilePath):
        return False

    return True
Esempio n. 4
0
def writeNetworkConfig(newNetworkConfig):
    networkConfig = configparser.ConfigParser(interpolation=None)

    try:
        networkConfig["network"] = {}
        networkConfig["network"]["version"] = str(_networkConfigVersion())
        networkConfig["network"]["serverHostname"] = newNetworkConfig["serverHostname"]
        networkConfig["network"]["domain"] = newNetworkConfig["domain"]
        networkConfig["network"]["realm"] = newNetworkConfig["realm"]
    except Exception as e:
        logging.error("Error when preprocessing new network configuration!")
        logging.exception(e)
        return False

    try:
        logging.info("Writing new network Configuration")
        with open(constants.networkConfigFilePath, 'w') as networkConfigFile:
            networkConfig.write(networkConfigFile)

    except Exception as e:
        logging.error("Failed!")
        logging.exception(e)
        return False

    return True
Esempio n. 5
0
def deleteFilesWithExtension(directory, extension):
    """
    Delete all files with a given extension in a given directory.

    :param directory: The path of the directory
    :type directory: str
    :param extension: The file extension
    :type extension: str
    :return: True on success, False otherwise
    :rtype: bool
    """
    if directory.endswith("/"):
        directory = directory[:-1]

    if not os.path.exists(directory):
        return True

    existingFiles = os.listdir(directory)

    for file in existingFiles:
        if file.endswith(extension):
            logging.info("* Deleting {}".format(file))
            if not deleteFile("{}/{}".format(directory, file)):
                logging.error("Failed!")
                return False

    return True
Esempio n. 6
0
def _installCaCertificate(domain, user):
    logging.info('Installing server ca certificate ... ')

    # try to mount the share
    rc, sysvolMountpoint = shares.getLocalSysvolPath()
    if not rc:
        logging.error("Failed to mount sysvol!")
        return False

    cacertPath = f"{sysvolMountpoint}/{domain}/tls/cacert.pem"
    cacertTargetPath = f"/var/lib/samba/private/tls/{domain}.pem"

    logging.info("Copying CA certificate from server to client!")
    try:
        Path(Path(cacertTargetPath).parent.absolute()).mkdir(parents=True,
                                                             exist_ok=True)
        shutil.copyfile(cacertPath, cacertTargetPath)
    except Exception as e:
        logging.error("Failed!")
        logging.exception(e)
        return False

    # make sure the file was successfully copied
    if not os.path.isfile(cacertTargetPath):
        logging.error('Failed to copy over CA certificate!')
        return False

    # unmount sysvol
    shares.unmountAllSharesOfUser(computer.krbHostName())

    return True
def _clearUserHomes(unattended=False):
    print("\nCAUTION! This will delete all userhomes of AD users!")
    if not unattended and not _askStep("clear all user homes now", False):
        return True

    if not _checkLoggedInUsers():
        return False

    if not _unmountAllCifsMounts():
        logging.info("Aborting deletion of user homes to prevent deleting data on the server.")
        return False

    userHomes = os.listdir("/home")

    logging.info("Deleting all user homes now!")
    for userHome in userHomes:
        if not user.isUserInAD(userHome):
            logging.info("* {} [SKIPPED]".format(userHome))
            continue

        logging.info("* {}".format(userHome))
        try:
            shutil.rmtree("/home/{}".format(userHome))
        except Exception as e:
            logging.error("* FAILED!")
            logging.exception(e)
        
        try:
            shutil.rmtree(constants.hiddenShareMountBasepath.format(userHome))
        except:
            pass
    
    logging.info("Done.")
    return True
def cleanTemplateUserGtkBookmarks():
    logging.info("Cleaning {} gtk bookmarks".format(constants.templateUser))
    gtkBookmarksFile = "/home/{0}/.config/gtk-3.0/bookmarks".format(user.username())

    if not os.path.isfile(gtkBookmarksFile):
        logging.warning("Gtk bookmarks file not found, skipping!")
        return

    fileHelper.removeLinesInFileContainingString(gtkBookmarksFile, constants.templateUser)
Esempio n. 9
0
def runLocalHook(hookType):
    logging.info("=== Running local hook on{0} ===".format(hookType.name))
    hookDir = _getLocalHookDir(hookType)
    if os.path.exists(hookDir):
        _prepareEnvironment()
        for fileName in os.listdir(hookDir):
            filePath = hookDir + "/" + fileName
            _runHookScript(filePath)
    logging.info("===> Finished running local hook on{0} ===".format(
        hookType.name))
Esempio n. 10
0
def _uninstallPrinter(name):
    logging.info("* Uninstalling Printer {}".format(name))
    uninstallCommand = ["lpadmin", "-x", name]
    #logging.debug("* running '{}'".format(installCommand))

    if not subprocess.call(uninstallCommand) == 0:
        logging.error("* Error uninstalling printer!")
        return False

    return True
Esempio n. 11
0
def join(domain, user):
    # join the domain using the kerberos ticket
    joinCommand = ["realm", "join", "-v", domain, "-U", user]
    if subprocess.call(joinCommand) != 0:
        print()
        logging.error('Failed! Did you enter the correct password?')
        return False

    logging.info("It looks like the domain was joined successfully.")
    return True
Esempio n. 12
0
def runRemoteHook(hookType):
    logging.info("=== Running remote hook on{0} ===".format(hookType.name))
    rc, hookScripts = _getRemoteHookScripts(hookType)

    if rc:
        _prepareEnvironment()
        _runHookScript(hookScripts[0])
        _runHookScript(hookScripts[1])

    logging.info("===> Finished running remote hook on{0} ===".format(
        hookType.name))
Esempio n. 13
0
def _clearUserCache(unattended=False):
    if not unattended and not _askStep("clear all cached users now"):
        return True

    if not _checkLoggedInUsers():
        return False

    realm.clearUserCache()

    logging.info("Done.")

    return realm.clearUserCache()
def _readTextfile(filePath):
    if not os.path.isfile(filePath):
        return False, None
    try:
        infile = codecs.open(filePath, 'r', encoding='utf-8', errors='ignore')
        content = infile.read()
        infile.close()
        return True, content
    except Exception as e:
        logging.info('Cannot read ' + filePath + '!')
        logging.exception(e)
        return False, None
Esempio n. 15
0
def patchKeytab():
    """
    Patches the `/etc/krb5.keytab` file. It inserts the correct hostname of the current computer.

    :return: True on success, False otherwise
    :rtype: bool
    """
    krb5KeytabFilePath = "/etc/krb5.keytab"
    logging.info("Patching {}".format(krb5KeytabFilePath))
    krb5KeytabUtil = Krb5KeytabUtil(krb5KeytabFilePath)

    try:
        krb5KeytabUtil.read()
    except:
        logging.error("Error reading {}".format(krb5KeytabFilePath))
        return False

    for entry in krb5KeytabUtil.keytab.entries:
        oldData = entry.principal.components[-1].data
        if len(entry.principal.components) == 1:
            newData = computer.hostname().upper() + "$"
            entry.principal.components[0].data = newData

        elif len(entry.principal.components) == 2 and (
                entry.principal.components[0].data == "host"
                or entry.principal.components[0].data == "RestrictedKrbHost"):
            rc, networkConfig = config.network()
            if not rc:
                continue

            newData = ""
            domain = networkConfig["domain"]
            if domain in entry.principal.components[1].data:
                newData = computer.hostname().lower() + "." + domain
            else:
                newData = computer.hostname().upper()

            entry.principal.components[1].data = newData

        logging.debug("{} was changed to {}".format(
            oldData, entry.principal.components[-1].data))

    logging.info("Trying to overwrite {}".format(krb5KeytabFilePath))
    try:
        result = krb5KeytabUtil.write()
    except:
        result = False

    if not result:
        logging.error("Error overwriting {}".format(krb5KeytabFilePath))

    return result
def uninstallAllPrintersOfUser(username):
    logging.info("Uninstalling all printers of {}".format(username))
    rc, installedPrinters = _getInstalledPrintersOfUser(username)

    if not rc:
        logging.error("Error getting printers!")
        return False

    for installedPrinter in installedPrinters:
        if not _uninstallPrinter(installedPrinter):
            return False

    return True
Esempio n. 17
0
def unmountAllSharesOfUser(username):
    logging.info(
        "=== Trying to unmount all shares of user {0} ===".format(username))
    for basedir in [
            constants.shareMountBasepath, constants.hiddenShareMountBasepath
    ]:
        shareMountBasedir = basedir.format(username)

        try:
            mountedShares = os.listdir(shareMountBasedir)
        except FileNotFoundError:
            logging.info(
                "Mount basedir {} does not exist -> nothing to unmount".format(
                    shareMountBasedir))
            continue

        for share in mountedShares:
            _unmountShare("{0}/{1}".format(shareMountBasedir, share))

        if len(os.listdir(shareMountBasedir)) > 0:
            logging.warning(
                "* Mount basedir {} is not empty so not removed!".format(
                    shareMountBasedir))
            return
        else:
            # Delete the directory
            logging.info("Deleting {0}...".format(shareMountBasedir))
            try:
                shutil.rmtree(shareMountBasedir)
            except Exception as e:
                logging.error("FAILED!")
                logging.exception(e)

    logging.info(
        "===> Finished unmounting all shares of user {0} ===".format(username))
Esempio n. 18
0
def _preparePam():
    # enable necessary pam modules
    logging.info('Updating pam configuration ... ')
    subprocess.call([
        'pam-auth-update', '--package', '--enable', 'libpam-mount',
        'pwquality', 'sss', '--force'
    ])
    ## mkhomedir was injected in template not using pam-auth-update
    subprocess.call([
        'pam-auth-update', '--package', '--remove', 'krb5', 'mkhomedir',
        '--force'
    ])

    return True
Esempio n. 19
0
def _prepareNetworkConfiguration(domain):
    logging.info("Preparing network configuration")
    rc, domainConfig = realm.getDomainConfig(domain)
    if not rc:
        logging.error("Could not read domain configuration")
        return False

    newNetworkConfig = {}
    newNetworkConfig["serverHostname"] = domainConfig["domain-controller"]
    newNetworkConfig["domain"] = domainConfig["domain-name"]
    newNetworkConfig["realm"] = domainConfig["domain-name"].upper()

    config.writeNetworkConfig(newNetworkConfig)

    return True
Esempio n. 20
0
def runLocalHook(hookType):
    """
    Run all scripts in a local hookdir

    :param hookType: The type of hook to run
    :type hookType: hooks.Type
    """
    logging.info("=== Running local hook on{0} ===".format(hookType.name))
    hookDir = _getLocalHookDir(hookType)
    if os.path.exists(hookDir):
        _prepareEnvironment()
        for fileName in os.listdir(hookDir):
            filePath = hookDir + "/" + fileName
            _runHookScript(filePath)
    logging.info("===> Finished running local hook on{0} ===".format(
        hookType.name))
Esempio n. 21
0
def runRemoteHook(hookType):
    """
    Run hookscript from sysvol

    :param hookType: The type of hook to run
    :type hookType: hooks.Type
    """
    logging.info("=== Running remote hook on{0} ===".format(hookType.name))
    rc, hookScripts = _getRemoteHookScripts(hookType)

    if rc:
        _prepareEnvironment()
        _runHookScript(hookScripts[0])
        _runHookScript(hookScripts[1])

    logging.info("===> Finished running remote hook on{0} ===".format(
        hookType.name))
Esempio n. 22
0
def _runHookScript(filePath):
    if not os.path.isfile(filePath):
        logging.warning(
            "* File {0} should be executed as hook but does not exist!".format(
                filePath))
        return
    if not os.access(filePath, os.X_OK):
        logging.warning(
            "* File {0} is in hook dir but not executable!".format(filePath))
        return

    logging.info("== Executing script {0} ==".format(filePath))

    result = subprocess.call([filePath])

    logging.info("==> Script {0} finished with exit code {1} ==".format(
        filePath, result))
Esempio n. 23
0
def _processDrivesPolicy(policyBasepath):
    logging.info("== Parsing a drive policy! ==")
    policyFile = "{}/User/Preferences/Drives/Drives.xml".format(policyBasepath)
    shareList = []

    rc, tree = _parseXmlPolicy(policyFile)

    if not rc:
        logging.error(
            "==> Error while reading Drives policy file, skipping! ==")
        return

    xmlDrives = tree.getroot()

    if not xmlDrives.tag == "Drives":
        logging.warning(
            "==> Drive policy xml File is of invalid format, skipping! ==")
        return

    for xmlDrive in xmlDrives:

        if xmlDrive.tag != "Drive" or ("disabled" in xmlDrive.attrib
                                       and xmlDrive.attrib["disabled"] == "1"):
            continue

        drive = {}
        drive["filters"] = []
        for xmlDriveProperty in xmlDrive:
            if xmlDriveProperty.tag == "Properties":
                try:
                    drive["label"] = xmlDriveProperty.attrib["label"]
                    drive["letter"] = xmlDriveProperty.attrib["letter"]
                    drive["path"] = xmlDriveProperty.attrib["path"]
                except Exception as e:
                    logging.warning(
                        "Exception when parsing a drive policy XML file")
                    logging.exception(e)
                    continue

            if xmlDriveProperty.tag == "Filters":
                drive["filters"] = _parseXmlFilters(xmlDriveProperty)

        shareList.append(drive)

    shareList = _processFilters(shareList)

    logging.info("Found shares:")
    for drive in shareList:
        logging.info("* {0}\t\t| {1}\t| {2}\t| {3}".format(
            drive["label"], drive["letter"], drive["path"], drive["filters"]))

        shares.mountShare(drive["path"],
                          shareName="{0} ({1}:)".format(
                              drive["label"], drive["letter"]))

    logging.info("==> Successfully parsed a drive policy! ==")
def _clearCaches(unattended=False):    
    if not unattended and not _askStep("clear journalctl and apt caches now"):
        return True

    logging.info("Cleaning caches..")
    logging.info("* apt")
    fileHelper.deleteAllInDirectory("/var/lib/apt/lists/")
    logging.info("* journalctl")
    subprocess.call(["journalctl", "--flush", "--rotate"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    subprocess.call(["journalctl", "--vacuum-time=1s"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    logging.info("Done.")
    return True
Esempio n. 25
0
def uninstallAllPrintersOfUser(username):
    """
    Uninstalls all printers of a given user

    :param username: The username of the user
    :type username: str
    :return: True on success, False otherwise
    :rtype: bool
    """
    logging.info("Uninstalling all printers of {}".format(username))
    rc, installedPrinters = _getInstalledPrintersOfUser(username)

    if not rc:
        logging.error("Error getting printers!")
        return False

    for installedPrinter in installedPrinters:
        if not _uninstallPrinter(installedPrinter):
            return False

    return True
Esempio n. 26
0
def _prepareServices():
    logging.info("Raloading systctl daemon")
    subprocess.call(["systemctl", "daemon-reload"])

    logging.info('Enabling services:')
    services = ['linuxmuster-linuxclient7', 'smbd', 'nmbd', 'sssd']
    for service in services:
        logging.info('* %s' % service)
        subprocess.call(['systemctl', 'enable', service + '.service'],
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)

    logging.info('Restarting services:')
    services = ['smbd', 'nmbd', 'systemd-timesyncd']
    for service in services:
        logging.info('* %s' % service)
        subprocess.call(['systemctl', 'restart', service + '.service'],
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)

    return True
Esempio n. 27
0
def _parsePolicy(policyDn):
    logging.info("=== Parsing policy [{0};{1}] ===".format(
        policyDn[0], policyDn[1]))

    # Check if the policy is disabled
    if policyDn[1] == 1:
        logging.info("===> Policy is disabled! ===")
        return True

    # Find policy in AD
    rc, policyAdObject = ldapHelper.searchOne("(distinguishedName={})".format(
        policyDn[0]))
    if not rc:
        logging.error("===> Could not find poilcy in AD! ===")
        return False, None

    # mount the share the policy is on (probaply already mounted, just to be sure)
    rc, localPolicyPath = shares.getMountpointOfRemotePath(
        policyAdObject["gPCFileSysPath"], hiddenShare=True, autoMount=True)
    if not rc:
        logging.error("===> Could not mount path of poilcy! ===")
        return False, None

    try:
        # parse drives
        _processDrivesPolicy(localPolicyPath)
        # parse printers
        _processPrintersPolicy(localPolicyPath)
    except Exception as e:
        logging.error("An error occured when parsing policy!")
        logging.exception(e)

    logging.info("===> Parsed policy [{0};{1}] ===".format(
        policyDn[0], policyDn[1]))
Esempio n. 28
0
def _upgradeNetworkConfig():
    logging.info("Upgrading network config.")
    rc, rawNetworkConfig = _readNetworkConfig()
    if not rc:
        return False

    rc, networkConfigVersion = _checkNetworkConfigVersion(rawNetworkConfig)
    if rc:
        logging.info("No need to upgrade, already up-to-date.")
        return True

    logging.info("Upgrading network config from {0} to {1}".format(networkConfigVersion, _networkConfigVersion()))
    
    if networkConfigVersion > _networkConfigVersion():
        logging.error("Cannot upgrade from a newer version to an older one!")
        return False

    try:
        if networkConfigVersion == 0:
            newNetworkConfig = {}
            newNetworkConfig["serverHostname"] = rawNetworkConfig["serverHostname"] + "." + rawNetworkConfig["domain"]
            newNetworkConfig["domain"] = rawNetworkConfig["domain"]
            newNetworkConfig["realm"] = rawNetworkConfig["domain"].upper()
            return writeNetworkConfig(newNetworkConfig)
    except Exception as e:
        logging.error("Error when upgrading network config!")
        logging.exception(e)
        return False

    return True
Esempio n. 29
0
def upgrade():
    """
    Performs an upgrade of the linuxmuster-linuxclient7. This is executed after the package is updated.

    :return: True on success, False otherwise
    :rtype: bool
    """
    if not isSetup():
        logging.info(
            "linuxmuster-linuxclient7 does not seem to be setup -> no upgrade is needed"
        )
        return True

    logging.info('#### linuxmuster-linuxclient7 upgrade ####')
    if not config.upgrade():
        return False

    if not _deleteObsoleteFiles():
        return False

    if not templates.applyAll():
        return False

    if not _prepareServices():
        return False

    rc, joinedDomains = realm.getJoinedDomains()
    if not rc:
        return False

    for domain in joinedDomains:
        _adjustSssdConfiguration(domain)

    logging.info('#### linuxmuster-linuxclient7 upgrade SUCCESSFULL ####')
    return True
Esempio n. 30
0
def _unmountShare(mountpoint):
    # check if mountpoint exists
    if (not os.path.exists(mountpoint)) or (not os.path.isdir(mountpoint)):
        logging.warning(
            f"* Could not unmount {mountpoint}, it does not exist.")

    # Try to unmount share
    logging.info("* Trying to unmount {0}...".format(mountpoint))
    if not subprocess.call(["umount", mountpoint]) == 0:
        logging.warning("* Failed!")
        if _directoryIsMountpoint(mountpoint):
            logging.warning("* It is still mounted! Exiting!")
            # Do not delete in this case! We might delete userdata!
            return
        logging.info("* It is not mounted! Continuing!")

    # check if the mountpoint is empty
    if len(os.listdir(mountpoint)) > 0:
        logging.warning(
            "* mountpoint {} is not empty so not removed!".format(mountpoint))
        return

    # Delete the directory
    logging.info("* Deleting {0}...".format(mountpoint))
    try:
        shutil.rmtree(mountpoint)
    except Exception as e:
        logging.error("* FAILED!")
        logging.exception(e)