Example #1
0
    def __init__(self, config):
        self.config = config

        util.initLogging(config["verbose"], config.get("log_path", ""),
                         config.get("enable_loggers", []))

        util.log("Default encoding: %s (file system: %s)" %
                 (sys.getdefaultencoding(), sys.getfilesystemencoding()))

        # Evaluate configuration and set defaults
        _checkConfig(config)
        provider_mapping = self.config["provider_mapping"]
        #        response_trailer = config.get("response_trailer", "")
        self._verbose = config.get("verbose", 2)

        lockStorage = config.get("locksmanager")
        if lockStorage is True:
            lockStorage = LockStorageDict()

        if not lockStorage:
            locksManager = None
        else:
            locksManager = LockManager(lockStorage)

        propsManager = config.get("propsmanager")
        if not propsManager:
            # Normalize False, 0 to None
            propsManager = None
        elif propsManager is True:
            propsManager = PropertyManager()

        mount_path = config.get("mount_path")

        # Instantiate DAV resource provider objects for every share
        self.providerMap = {}
        for (share, provider) in provider_mapping.items():
            # Make sure share starts with, or is, '/'
            share = "/" + share.strip("/")

            # We allow a simple string as 'provider'. In this case we interpret
            # it as a file system root folder that is published.
            if isinstance(provider, basestring):
                provider = FilesystemProvider(provider)

            assert isinstance(provider, DAVProvider)

            provider.setSharePath(share)
            if mount_path:
                provider.setMountPath(mount_path)

            # TODO: someday we may want to configure different lock/prop managers per provider
            provider.setLockManager(locksManager)
            provider.setPropManager(propsManager)

            self.providerMap[share] = {
                "provider": provider,
                "allow_anonymous": False
            }

        # Define WSGI application stack
        application = RequestResolver()

        domain_controller = None
        dir_browser = config.get("dir_browser", {})
        middleware_stack = config.get("middleware_stack", [])

        # Replace WsgiDavDirBrowser to custom class for backward compatibility only
        # In normal way you should insert it into middleware_stack
        if dir_browser.get("enable",
                           True) and "app_class" in dir_browser.keys():
            config["middleware_stack"] = [
                m if m != WsgiDavDirBrowser else dir_browser['app_class']
                for m in middleware_stack
            ]

        for mw in middleware_stack:
            if mw.isSuitable(config):
                if self._verbose >= 2:
                    print "Middleware %s is suitable" % mw
                application = mw(application, config)

                if issubclass(mw, HTTPAuthenticator):
                    domain_controller = application.getDomainController()
                    # check anonymous access
                    for share, data in self.providerMap.items():
                        if application.allowAnonymousAccess(share):
                            data['allow_anonymous'] = True
            else:
                if self._verbose >= 2:
                    print "Middleware %s is not suitable" % mw

        # Print info
        if self._verbose >= 2:
            print "Using lock manager: %r" % locksManager
            print "Using property manager: %r" % propsManager
            print "Using domain controller: %s" % domain_controller
            print "Registered DAV providers:"
            for share, data in self.providerMap.items():
                hint = " (anonymous)" if data['allow_anonymous'] else ""
                print "  Share '%s': %s%s" % (share, provider, hint)
        if self._verbose >= 1:
            for share, data in self.providerMap.items():
                if data['allow_anonymous']:
                    # TODO: we should only warn here, if --no-auth is not given
                    print "WARNING: share '%s' will allow anonymous access." % share

        self._application = application
Example #2
0
    def __init__(self, config):

        self.config = copy.deepcopy(DEFAULT_CONFIG)
        util.deep_update(self.config, config)
        # self.config.update(config)
        config = self.config

        # Evaluate configuration and set defaults
        _check_config(config)

        #        response_trailer = config.get("response_trailer", "")
        self.verbose = config.get("verbose", 3)

        lockStorage = config.get("lock_manager")
        if lockStorage is True:
            lockStorage = LockStorageDict()

        if not lockStorage:
            self.locksManager = None
        else:
            self.locksManager = LockManager(lockStorage)

        self.propsManager = config.get("property_manager")
        if not self.propsManager:
            # Normalize False, 0 to None
            self.propsManager = None
        elif self.propsManager is True:
            self.propsManager = PropertyManager()

        self.mount_path = config.get("mount_path")

        # Instantiate DAV resource provider objects for every share
        # provider_mapping may contain the args that are passed to a `FilesystemProvider`
        # instance:
        #     <mount_path>: <folder_path>
        # or
        #     <mount_path>: [folder_path, is_readonly]
        # or contain a complete new instance:
        #     <mount_path>: <DAVProvider Instance>

        provider_mapping = self.config["provider_mapping"]

        self.providerMap = {}
        self.sortedShareList = None
        for share, provider in provider_mapping.items():
            self.add_provider(share, provider)

        domain_controller = None

        # Define WSGI application stack
        middleware_stack = config.get("middleware_stack", [])
        mw_list = []

        # This is the 'outer' application, i.e. the WSGI application object that
        # is eventually called by the server.
        self.application = self

        # When building up the middleware stack, this app will be wrapped and replaced by the
        # next middleware in the list.
        # The `middleware_stack` is configured such that the first app in the list should be
        # called first. But since every app wraps its predecessor, we iterate in reverse
        # order:
        for mw in reversed(middleware_stack):
            # The middleware stack configuration may contain plain strings, dicts,
            # classes, or objects
            app = None
            if compat.is_basestring(mw):
                # If a plain string is passed, try to import it, assuming BaseMiddleware
                # signature
                app_class = dynamic_import_class(mw)
                app = app_class(self, self.application, config)
            elif type(mw) is dict:
                # If a dict with one entry is passed, use the key as module/class name
                # and the value as constructor arguments (positional or kwargs).
                assert len(mw) == 1
                name, args = list(mw.items())[0]
                expand = {"${application}": self.application}
                app = dynamic_instantiate_middleware(name, args, expand)
            elif inspect.isclass(mw):
                # If a class is passed, assume BaseMiddleware (or compatible)
                assert issubclass(
                    mw, BaseMiddleware
                )  # TODO: remove this assert with 3.0
                app = mw(self, self.application, config)
            else:
                # Otherwise assume an initialized middleware instance
                app = mw

            # TODO: We should try to generalize this specific code:
            if isinstance(app, HTTPAuthenticator):
                domain_controller = app.get_domain_controller()
                # Check anonymous access
                for share, data in self.providerMap.items():
                    if app.allow_anonymous_access(share):
                        data["allow_anonymous"] = True

            # Add middleware to the stack
            if app:
                mw_list.append(app)
                self.application = app
            else:
                _logger.error("Could not add middleware {}.".format(mw))

        # Print info
        _logger.info(
            "WsgiDAV/{} Python/{} {}".format(
                __version__, util.PYTHON_VERSION, platform.platform(aliased=True)
            )
        )
        if self.verbose >= 4:
            _logger.info(
                "Default encoding: {!r} (file system: {!r})".format(
                    sys.getdefaultencoding(), sys.getfilesystemencoding()
                )
            )
            _logger.info("Lock manager:      {}".format(self.locksManager))
            _logger.info("Property manager:  {}".format(self.propsManager))
            _logger.info("Domain controller: {}".format(domain_controller))

            # We traversed the stack in reverse order. Now revert again, so
            # we see the order that was configured:
            _logger.info("Middleware stack:")
            for mw in reversed(mw_list):
                _logger.info("  - {}".format(mw))

            _logger.info("Registered DAV providers by route:")
            for share in self.sortedShareList:
                data = self.providerMap[share]
                hint = " (anonymous)" if data["allow_anonymous"] else ""
                _logger.info("  - '{}': {}{}".format(share, data["provider"], hint))

        for share, data in self.providerMap.items():
            if data["allow_anonymous"]:
                # TODO: we should only warn here, if --no-auth is not given
                _logger.warn("Share '{}' will allow anonymous access.".format(share))
        return
Example #3
0
    def __init__(self, config):
        self.config = config

        # Do not initialize logging here, because we want to keep silence in library-mode
        # util.initLogging(config["verbose"], config.get("enable_loggers", []))

        _logger.info("Default encoding: {} (file system: {})".format(
            sys.getdefaultencoding(), sys.getfilesystemencoding()))

        # Evaluate configuration and set defaults
        _checkConfig(config)
        provider_mapping = self.config["provider_mapping"]
        #        response_trailer = config.get("response_trailer", "")
        self._verbose = config.get("verbose", 3)

        lockStorage = config.get("locksmanager")
        if lockStorage is True:
            lockStorage = LockStorageDict()

        if not lockStorage:
            locksManager = None
        else:
            locksManager = LockManager(lockStorage)

        propsManager = config.get("propsmanager")
        if not propsManager:
            # Normalize False, 0 to None
            propsManager = None
        elif propsManager is True:
            propsManager = PropertyManager()

        mount_path = config.get("mount_path")

        # Instantiate DAV resource provider objects for every share
        self.providerMap = {}
        for (share, provider) in provider_mapping.items():
            # Make sure share starts with, or is, '/'
            share = "/" + share.strip("/")

            # We allow a simple string as 'provider'. In this case we interpret
            # it as a file system root folder that is published.
            if compat.is_basestring(provider):
                provider = FilesystemProvider(provider)

            assert isinstance(provider, DAVProvider)

            provider.setSharePath(share)
            if mount_path:
                provider.setMountPath(mount_path)

            # TODO: someday we may want to configure different lock/prop
            # managers per provider
            provider.setLockManager(locksManager)
            provider.setPropManager(propsManager)

            self.providerMap[share] = {
                "provider": provider,
                "allow_anonymous": False,
            }

        # Define WSGI application stack
        application = RequestResolver()

        domain_controller = None
        dir_browser = config.get("dir_browser", {})
        middleware_stack = config.get("middleware_stack", [])

        if dir_browser.get("app_class"):
            _logger.error("")
        # # Replace WsgiDavDirBrowser to custom class for backward compatibility only
        # # In normal way you should insert it into middleware_stack
        # if dir_browser.get("enable", True) and "app_class" in dir_browser.keys():
        #     config["middleware_stack"] = [m if m != WsgiDavDirBrowser else dir_browser[
        #         "app_class"] for m in middleware_stack]

        _logger.info("Middleware stack:")
        for mw in middleware_stack:
            if mw.isSuitable(config):
                # if self._verbose >= 2:
                _logger.info("  - {}".format(mw))
                application = mw(application, config)

                if issubclass(mw, HTTPAuthenticator):
                    domain_controller = application.getDomainController()
                    # check anonymous access
                    for share, data in self.providerMap.items():
                        if application.allowAnonymousAccess(share):
                            data["allow_anonymous"] = True
            else:
                # if self._verbose >= 2:
                _logger.warn(
                    "- SKIPPING middleware {} (not suitable)".format(mw))

        # Print info
        if self._verbose >= 3:
            _logger.info("Using lock manager: {!r}".format(locksManager))
            _logger.info("Using property manager: {!r}".format(propsManager))
            _logger.info(
                "Using domain controller: {!r}".format(domain_controller))
            _logger.info("Registered DAV providers:")
            for share, data in self.providerMap.items():
                hint = " (anonymous)" if data["allow_anonymous"] else ""
                _logger.info("  Share '{}': {}{}".format(
                    share, provider, hint))
        if self._verbose >= 2:
            for share, data in self.providerMap.items():
                if data["allow_anonymous"]:
                    # TODO: we should only warn here, if --no-auth is not given
                    _logger.warn(
                        "WARNING: share '{}' will allow anonymous access.".
                        format(share))

        self._application = application
Example #4
0
    def __init__(self, config):

        self.config = copy.deepcopy(DEFAULT_CONFIG)
        util.deep_update(self.config, config)
        config = self.config

        # Evaluate configuration and set defaults
        _check_config(config)

        self.verbose = config.get("verbose", 3)

        hotfixes = config.get("hotfixes", {})

        self.re_encode_path_info = hotfixes.get("re_encode_path_info", None)
        if self.re_encode_path_info is None:
            self.re_encode_path_info = compat.PY3

        self.unquote_path_info = hotfixes.get("unquote_path_info", False)

        lock_storage = config.get("lock_manager")
        if lock_storage is True:
            lock_storage = LockStorageDict()

        if not lock_storage:
            self.lock_manager = None
        else:
            self.lock_manager = LockManager(lock_storage)

        self.prop_manager = config.get("property_manager")
        if not self.prop_manager:
            # Normalize False, 0 to None
            self.prop_manager = None
        elif self.prop_manager is True:
            self.prop_manager = PropertyManager()

        self.mount_path = config.get("mount_path")
        auth_conf = config.get("http_authenticator", {})

        # Instantiate DAV resource provider objects for every share.
        # provider_mapping may contain the args that are passed to a
        # `FilesystemProvider` instance:
        #     <mount_path>: <folder_path>
        # or
        #     <mount_path>: { "root": <folder_path>, "readonly": True }
        # or contain a complete new instance:
        #     <mount_path>: <DAVProvider Instance>

        provider_mapping = self.config["provider_mapping"]

        self.provider_map = {}
        self.sorted_share_list = None
        for share, provider in provider_mapping.items():
            self.add_provider(share, provider)

        self.http_authenticator = None
        domain_controller = None

        # Define WSGI application stack
        middleware_stack = config.get("middleware_stack", [])
        mw_list = []

        # This is the 'outer' application, i.e. the WSGI application object that
        # is eventually called by the server.
        self.application = self

        # The `middleware_stack` is configured such that the first app in the
        # list should be called first. Since every app wraps its predecessor, we
        # iterate in reverse order:
        for mw in reversed(middleware_stack):
            # The middleware stack configuration may contain plain strings, dicts,
            # classes, or objects
            app = None
            if compat.is_basestring(mw):
                # If a plain string is passed, try to import it, assuming
                # `BaseMiddleware` signature
                app_class = dynamic_import_class(mw)
                app = app_class(self, self.application, config)
            elif type(mw) is dict:
                # If a dict with one entry is passed, use the key as module/class name
                # and the value as constructor arguments (positional or kwargs).
                assert len(mw) == 1
                name, args = list(mw.items())[0]
                expand = {"${application}": self.application}
                app = dynamic_instantiate_middleware(name, args, expand)
            elif inspect.isclass(mw):
                # If a class is passed, assume BaseMiddleware (or compatible)
                assert issubclass(
                    mw, BaseMiddleware)  # TODO: remove this assert with 3.0
                app = mw(self, self.application, config)
            else:
                # Otherwise assume an initialized middleware instance
                app = mw

            # Remember
            if isinstance(app, HTTPAuthenticator):
                self.http_authenticator = app
                domain_controller = app.get_domain_controller()

            # Add middleware to the stack
            if app:
                if callable(getattr(app, "is_disabled",
                                    None)) and app.is_disabled():
                    _logger.warning(
                        "App {}.is_disabled() returned True: skipping.".format(
                            app))
                else:
                    mw_list.append(app)
                    self.application = app
            else:
                _logger.error("Could not add middleware {}.".format(mw))

        domain_controller
        # Print info
        _logger.info("WsgiDAV/{} Python/{} {}".format(
            __version__, util.PYTHON_VERSION, platform.platform(aliased=True)))
        if self.verbose >= 4:
            _logger.info("Default encoding: {!r} (file system: {!r})".format(
                sys.getdefaultencoding(), sys.getfilesystemencoding()))

        if self.verbose >= 3:
            _logger.info("Lock manager:      {}".format(self.lock_manager))
            _logger.info("Property manager:  {}".format(self.prop_manager))
            _logger.info("Domain controller: {}".format(domain_controller))

        if self.verbose >= 4:
            # We traversed the stack in reverse order. Now revert again, so
            # we see the order that was configured:
            _logger.info("Middleware stack:")
            for mw in reversed(mw_list):
                _logger.info("  - {}".format(mw))

        if self.verbose >= 3:
            _logger.info("Registered DAV providers by route:")
            for share in self.sorted_share_list:
                provider = self.provider_map[share]
                hint = (" (anonymous)"
                        if domain_controller.is_share_anonymous(share) else "")
                _logger.info("  - '{}': {}{}".format(share, provider, hint))

        if auth_conf.get("accept_basic") and not config.get("ssl_certificate"):
            _logger.warning(
                "Basic authentication is enabled: It is highly recommended to enable SSL."
            )

        if domain_controller:
            for share, provider in self.provider_map.items():
                if domain_controller.is_share_anonymous(share):
                    _logger.warning(
                        "Share '{}' will allow anonymous {} access.".format(
                            share,
                            "read" if provider.is_readonly() else "write"))
        return
Example #5
0
    def __init__(self, config):
        self.config = config

        util.initLogging(config["verbose"], config.get("enable_loggers", []))

        util.log("Default encoding: %s (file system: %s)" %
                 (sys.getdefaultencoding(), sys.getfilesystemencoding()))

        # Evaluate configuration and set defaults
        _checkConfig(config)
        provider_mapping = self.config["provider_mapping"]
        #        response_trailer = config.get("response_trailer", "")
        self._verbose = config.get("verbose", 2)

        lockStorage = config.get("locksmanager")
        if lockStorage is True:
            lockStorage = LockStorageDict()

        if not lockStorage:
            locksManager = None
        else:
            locksManager = LockManager(lockStorage)

        propsManager = config.get("propsmanager")
        if not propsManager:
            # Normalize False, 0 to None
            propsManager = None
        elif propsManager is True:
            propsManager = PropertyManager()

        mount_path = config.get("mount_path")

        user_mapping = self.config.get("user_mapping", {})
        domainController = config.get(
            "domaincontroller") or WsgiDAVDomainController(user_mapping)
        isDefaultDC = isinstance(domainController, WsgiDAVDomainController)

        # authentication fields
        authacceptbasic = config.get("acceptbasic", True)
        authacceptdigest = config.get("acceptdigest", True)
        authdefaultdigest = config.get("defaultdigest", True)

        # Check configuration for NTDomainController
        # We don't use 'isinstance', because include would fail on non-windows boxes.
        wdcName = "NTDomainController"
        if domainController.__class__.__name__ == wdcName:
            if authacceptdigest or authdefaultdigest or not authacceptbasic:
                util.warn(
                    "WARNING: %s requires basic authentication.\n\tSet acceptbasic=True, acceptdigest=False, defaultdigest=False"
                    % wdcName)

        # Instantiate DAV resource provider objects for every share
        self.providerMap = {}
        for (share, provider) in provider_mapping.items():
            # Make sure share starts with, or is, '/'
            share = "/" + share.strip("/")

            # We allow a simple string as 'provider'. In this case we interpret
            # it as a file system root folder that is published.
            if isinstance(provider, basestring):
                provider = FilesystemProvider(provider)

            assert isinstance(provider, DAVProvider)

            provider.setSharePath(share)
            if mount_path:
                provider.setMountPath(mount_path)

            # TODO: someday we may want to configure different lock/prop managers per provider
            provider.setLockManager(locksManager)
            provider.setPropManager(propsManager)

            self.providerMap[share] = provider

        if self._verbose >= 2:
            print "Using lock manager: %r" % locksManager
            print "Using property manager: %r" % propsManager
            print "Using domain controller: %s" % domainController
            print "Registered DAV providers:"
            for share, provider in self.providerMap.items():
                hint = ""
                if isDefaultDC and not user_mapping.get(share):
                    hint = " (anonymous)"
                print "  Share '%s': %s%s" % (share, provider, hint)

        # If the default DC is used, emit a warning for anonymous realms
        if isDefaultDC and self._verbose >= 1:
            for share in self.providerMap:
                if not user_mapping.get(share):
                    # TODO: we should only warn here, if --no-auth is not given
                    print "WARNING: share '%s' will allow anonymous access." % share

        # Define WSGI application stack
        application = RequestResolver()

        if config.get("dir_browser") and config["dir_browser"].get(
                "enable", True):
            application = WsgiDavDirBrowser(application)

        application = HTTPAuthenticator(application, domainController,
                                        authacceptbasic, authacceptdigest,
                                        authdefaultdigest)
        application = ErrorPrinter(application, catchall=False)

        application = WsgiDavDebugFilter(application, config)

        self._application = application