Example #1
0
 def are_valid_credentials(self, username, password):
     """The valid users string in the config file is in the form:
         username=bill
         password=frank """
     valid_username = rdw_config.get_config(
         "username", self.configFilePath)
     valid_password = rdw_config.get_config(
         "password", self.configFilePath)
     return valid_username == username and valid_password == password
Example #2
0
 def _connect(self):
     import MySQLdb
     sqlHost = rdw_config.get_config("MySQLHost", self.configFilePath)
     sqlUsername = rdw_config.get_config(
         "MySQLUsername", self.configFilePath)
     sqlPassword = rdw_config.get_config(
         "MySQLPassword", self.configFilePath)
     sqlDatabaseName = rdw_config.get_config(
         "MySQLDatabase", self.configFilePath)
     self.sqlConnection = MySQLdb.connect(
         host=sqlHost, user=sqlUsername, passwd=sqlPassword, db=sqlDatabaseName)
Example #3
0
    def restore(self, name, restore_date, use_zip):
        """Used to restore the given file located in this path."""
        assert isinstance(name, str)
        assert isinstance(restore_date, rdw_helpers.rdwTime)
        name = name.lstrip(b"/")

        # Determine the file name to be restore (from rdiff-backup
        # point of view).
        file_to_restore = os.path.join(self.full_path, name)
        file_to_restore = self.repo.unquote(file_to_restore)

        # Convert the date into epoch.
        date_epoch = str(restore_date.getSeconds())

        # Define a location where to restore the data
        if name == b"" and self.path == b"":
            filename = b"root"
        if self.path != b"":
            filename = os.path.basename(self.path)
        if name != b"":
            filename = name
        # Generate a temporary location used to restore data.
        tempdir = rdw_helpers.encode_s(rdw_config.get_config("tempdir",
                                                             default=None))
        output = os.path.join(tempfile.mkdtemp(dir=tempdir), filename)

        # Execute rdiff-backup to restore the data.
        logger.info(b"execute rdiff-backup --restore-as-of=%s '%s' '%s'" %
                    (date_epoch, file_to_restore, output))
        results = self._execute(
            b"rdiff-backup",
            b"--restore-as-of=" + date_epoch,
            file_to_restore,
            output)

        # Check the result
        if results['exitCode'] != 0 or not os.access(output, os.F_OK):
            error = results['stderr']
            if not error:
                error = '''rdiff-backup claimed success, but did not restore
                        anything. This indicates a bug in rdiffweb. Please
                        report this to a developer.'''
            raise UnknownError('unable to restore!\n' + error)

        # The path restored is a directory and need to be archived using zip
        # or tar
        if os.path.isdir(output):
            output_dir = output
            try:
                if use_zip:
                    output = output_dir + ZIP_SUFFIX
                    self._recursiveZipDir(output_dir, output)
                else:
                    output = output_dir + TARGZ_SUFFIX
                    self._recursiveTarDir(output_dir, output)
            finally:
                rdw_helpers.remove_dir(output_dir)

        # Return the location of the file to be restored
        return output
Example #4
0
 def run(self):
     spiderInterval = rdw_config.get_config("autoUpdateRepos")
     if spiderInterval:
         spiderInterval = int(spiderInterval)
         while True:
             findReposForAllUsers()
             self.killEvent.wait(60 * spiderInterval)
             if self.killEvent.isSet():
                 return
Example #5
0
    def _migrateExistingData(self):
        """ If we don't have any data, we may be using a sqlite interface for
        the first time. See if they have another database backend specified,
        and if they do, try to migrate the data."""

        if self._getTables():
            return

        cursor = self.sqlConnection.cursor()
        cursor.execute("BEGIN TRANSACTION")
        for statement in self._getCreateStatements():
            cursor.execute(statement)

        if self._autoConvertDatabase:
            prevDBType = rdw_config.get_config(
                "UserDB", self.configFilePath)
            if prevDBType.lower() == "mysql":
                print 'Converting database from mysql...'
                import db_mysql
                prevDB = db_mysql.mysqlUserDB(self.configFilePath)
                users = prevDB._executeQuery(
                    "SELECT UserID, Username, Password, UserRoot, IsAdmin, UserEmail, RestoreFormat FROM users")
                cursor.executemany(
                    "INSERT INTO users (UserID, Username, Password, UserRoot, IsAdmin, UserEmail, RestoreFormat) values (?, ?, ?, ?, ?, ?, ?)", users)

                repos = prevDB._executeQuery(
                    "SELECT UserID, RepoPath, MaxAge FROM repos")
                cursor.executemany(
                    "INSERT INTO repos (UserID, RepoPath, MaxAge) values (?, ?, ?)", repos)
            elif prevDBType.lower() == "file":
                print 'Converting database from file...'
                import db_file
                prevDB = db_file.fileUserDB(self.configFilePath)
                username = rdw_config.get_config(
                    "username", self.configFilePath)
                password = rdw_config.get_config(
                    "password", self.configFilePath)
                self.add_user(username)
                self.set_password(username, None, password)
                self.set_info(username, prevDB.get_root_dir(username), True)
                self.set_repos(username, prevDB.get_repos(username))

        cursor.execute("COMMIT TRANSACTION")
Example #6
0
    def __init__(self, configFilePath=None, autoConvertDatabase=True):
        self.configFilePath = configFilePath
        # Get database location.
        self._databaseFilePath = rdw_config.get_config(
            "SqliteDBFile", self.configFilePath)
        # If the database path is not define default to /etc/rdiffweb/rdw.db
        if self._databaseFilePath == "":
            self._databaseFilePath = "/etc/rdiffweb/rdw.db"

        self._autoConvertDatabase = autoConvertDatabase
        self.userRootCache = {}
        self._connect()
        self._migrateExistingData()
Example #7
0
    def __init__(self, delegate, configFilePath=None):
        """Create a new LDAP Database for authentication. Some behaviour are
        delegate to external database."""

        self.delegate = delegate
        self.configFilePath = configFilePath

        # Get LDAP configuration parameters
        self.uri = rdw_config.get_config(
            "LdapUri", self.configFilePath, None)
        if self.uri is None:
            raise "LdapUri must be define in configuration"
        self.tls = rdw_config.get_config(
            "LdapTls", self.configFilePath).lower() == "true"
        self.base_dn = rdw_config.get_config(
            "LdapBaseDn", self.configFilePath, None)
        if self.uri is None:
            raise "LdapUri must be define in configuration"
        self.attribute = rdw_config.get_config(
            "LdapAttribute", self.configFilePath, "uid")
        self.scope = rdw_config.get_config(
            "LdapScope", self.configFilePath, "subtree")
        if self.scope == "base":
            self.scope = ldap.SCOPE_BASE
        elif self.scope == "onelevel":
            self.scope = ldap.SCOPE_ONELEVEL
        else:
            self.scope = ldap.SCOPE_SUBTREE
        self.filter = rdw_config.get_config(
            "LdapFilter", self.configFilePath, "(objectClass=*)")
        self.bind_dn = rdw_config.get_config(
            "LdapBindDn", self.configFilePath, "")
        self.bind_password = rdw_config.get_config(
            "LdapBindPassword", self.configFilePath, "")
        # Get Version
        self.version = rdw_config.get_config_int(
            "LdapVersion", self.configFilePath, 3)
        # Get Network timeout
        self.network_timeout = rdw_config.get_config_int(
            "LdapNetworkTimeout", self.configFilePath, 100)
        # Get Timeout
        self.timeout = rdw_config.get_config_int(
            "LdapTimeout", self.configFilePath, 300)
        # Check if password change are allowed.
        self.allow_password_change = rdw_config.get_config_boolean(
            "LdapAllowPasswordChange", self.configFilePath)
Example #8
0
    def run(self):
        self.notifier = emailNotifier()
        if not self.notifier.notificationsEnabled():
            return
        emailTimeStr = rdw_config.get_config("emailNotificationTime")
        while True:
            emailTime = time.strptime(emailTimeStr, "%H:%M")
            now = datetime.datetime.now()
            nextEmailTime = now.replace(
                hour=emailTime.tm_hour, minute=emailTime.tm_min, second=0, microsecond=0)
            if nextEmailTime < now:
                nextEmailTime = nextEmailTime.replace(
                    day=nextEmailTime.day + 1)
            delta = (nextEmailTime - now).seconds
            self.killEvent.wait(delta)
            if self.killEvent.isSet():
                return

            self.notifier.sendEmails()
Example #9
0
 def get_userdb_module(self):
     # Return a different implementation according to UserDB configuration.
     prevDBType = rdw_config.get_config("UserDB")
     if prevDBType.lower() == "ldap":
         import db_ldap
         import db_sqlite
         return db_ldap.ldapUserDB(db_sqlite.sqliteUserDB())
     elif prevDBType.lower() == "mysql":
         import db_mysql
         return db_mysql.mysqlUserDB()
     elif prevDBType.lower() == "file":
         import db_file
         return db_file.fileUserDB()
     elif prevDBType == "" or prevDBType.lower() == "sqlite":
         import db_sqlite
         return db_sqlite.sqliteUserDB()
     else:
         raise ValueError(
             "Invalid user database type. Re-configure rdiffweb.")
Example #10
0
 def _getEmailUsername(self):
     return rdw_config.get_config("emailUsername")
Example #11
0
 def _getEmailHost(self):
     return rdw_config.get_config("emailHost")
Example #12
0
 def _getNotificationTimeStr(self):
     return rdw_config.get_config("emailNotificationTime")
Example #13
0
 def _getEmailPassword(self):
     return rdw_config.get_config("emailPassword")
Example #14
0
 def get_repos(self, username):
     """The user home dirs string in the config file is in the form of username:/data/dir|/data/dir2..."""
     if not self.exists(username):
         return None
     return rdw_config.get_config("UserRepoPaths", self.configFilePath).split("|")
Example #15
0
 def get_root_dir(self, username):
     if not self.exists(username):
         return None
     return rdw_config.get_config("UserRoot", self.configFilePath)
Example #16
0
def start():
    """Start rdiffweb deamon."""
    # Parse command line options
    debug = False
    autoReload = False
    pidFile = ""
    logFile = ""
    logAccessFile = ""

    opts, extraparams = getopt.getopt(sys.argv[1:],
                                      'vdr',
                                      ['debug',
                                       'log-file=',
                                       'log-access-file=',
                                       'pid-file=',
                                       'background',
                                       'autoreload'])
    for option, value in opts:
        if option in ['-d', '--debug']:
            debug = True
        if option in ['-r', '--autoreload']:
            autoReload = True
        elif option in ['--log-file']:
            logFile = value
        elif option in ['--log-access-file']:
            logAccessFile = value
        elif option in ['--pid-file']:
            pidFile = value
        elif option in ['--background']:
            rdw_helpers.daemonize()

    # Wait to write out to the pidfile until after we've (possibly) been
    # daemonized
    if pidFile:
        # Write our process id to specified file, so we can be killed later
        open(pidFile, 'a').write(str(os.getpid()) + "\n")

    # Configure logging
    logformat = '[%(asctime)s][%(levelname)-7s][%(name)s] %(message)s'
    level = logging.DEBUG if debug else logging.INFO
    if logFile:
        logging.basicConfig(filename=logFile, level=level, format=logformat)
    else:
        logging.basicConfig(level=level, format=logformat)
    if logAccessFile:
        logging.root.handlers[0].addFilter(NotFilter("cherrypy.access"))
    logging.root.handlers[0].addFilter(ContextFilter())
    # Check if configuration file exists
    config_file = rdw_config.get_config_file()
    if not os.access(config_file, os.F_OK):
        logger.warn("configuration file is not accessible: %s" % config_file)

    # Get configuration
    serverHost = rdw_config.get_config("ServerHost", default="0.0.0.0")
    try:
        serverPort = int(rdw_config.get_config("ServerPort", default="8080"))
    except ValueError:
        logger.error("ServerPort should be a port number")
        sys.exit(1)
    sslCertificate = rdw_config.get_config("SslCertificate")
    sslPrivateKey = rdw_config.get_config("SslPrivateKey")

    # Define the locales directory
    localesdir = os.path.split(inspect.getfile(inspect.currentframe()))[0]
    localesdir = os.path.realpath(os.path.abspath(localesdir))
    localesdir = os.path.join(localesdir, 'locales/')

    environment = "development"
    if not debug:
        environment = "production"
    global_settings = {
        'tools.encode.on': True,
        'tools.encode.encoding': 'utf-8',
        'tools.gzip.on': True,
        'tools.sessions.on': True,
        'tools.authform.on': True,
        'autoreload.on': autoReload,
        'server.socket_host': serverHost,
        'server.socket_port': serverPort,
        'server.log_file': logFile,
        'server.ssl_certificate': sslCertificate,
        'server.ssl_private_key': sslPrivateKey,
        'log.screen': False,
        'log.access_file': logAccessFile,
        'server.environment': environment,
    }

    page_settings = {
        '/': {
            'tools.authform.on': True,
            'tools.setup.on': True,
            'tools.i18n.on': True,
            'tools.i18n.default': 'en_US',
            'tools.i18n.mo_dir': localesdir,
            'tools.i18n.domain': 'messages'
        },
        '/login': {
            'tools.authform.on': False,
        },
        '/status/feed': {
            'tools.authform.on': False,
            'tools.authbasic.on': True,
            'tools.authbasic.checkpassword': page_login.rdiffLoginPage().checkpassword
        },
        '/static': {
            'tools.staticdir.on': True,
            'tools.staticdir.root': os.path.abspath(os.path.dirname(__file__)),
            'tools.staticdir.dir': "static",
            'tools.authform.on': False,
            'tools.setup.on': False,
        },
        '/setup': {
            'tools.setup.on': False,
            'tools.authform.on': False,
            'tools.sessions.on': False,
        }
    }

    if rdw_config.get_config("SessionStorage").lower() == "disk":
        sessionDir = rdw_config.get_config("SessionDir")
        if (os.path.exists(sessionDir)
                and os.path.isdir(sessionDir)
                and os.access(sessionDir, os.W_OK)):
            logger.info("Setting session mode to disk in directory %s" %
                        sessionDir)
            global_settings['tools.sessions.on'] = True
            global_settings['tools.sessions.storage_type'] = 'file'
            global_settings['tools.sessions.storage_path'] = sessionDir

    cherrypy.config.update(global_settings)
    root = page_locations.rdiffLocationsPage()
    root.setup = page_setup.rdiffSetupPage()
    root.login = page_login.rdiffLoginPage()
    root.logout = page_logout.rdiffLogoutPage()
    root.browse = page_browse.rdiffBrowsePage()
    root.restore = page_restore.rdiffRestorePage()
    root.history = page_history.rdiffHistoryPage()
    root.status = page_status.rdiffStatusPage()
    root.admin = page_admin.rdiffAdminPage()
    root.prefs = page_prefs.rdiffPreferencesPage()

    # Start repo spider thread
    if not debug:
        killEvent = threading.Event()

        rdw_spider_repos.startRepoSpiderThread(killEvent)
        email_notification.startEmailNotificationThread(killEvent)
        if hasattr(cherrypy.engine, 'subscribe'):  # CherryPy >= 3.1
            cherrypy.engine.subscribe('stop', lambda: killEvent.set())
        else:
            cherrypy.engine.on_stop_engine_list.append(lambda: killEvent.set())  # @UndefinedVariable

    # Start web server
    cherrypy.quickstart(root, config=page_settings)
Example #17
0
 def exists(self, username):
     valid_username = rdw_config.get_config(
         "username", self.configFilePath)
     return valid_username == username
Example #18
0
 def _getEmailSender(self):
     return rdw_config.get_config("emailSender")