diff --git a/pom.xml b/pom.xml
index 04301f62d6d6b9f05fc1c3b6892e70b8db52dc53..ecab49f7a9b79c31d7985872b82e6b01dea35313 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2289,7 +2289,7 @@
 		<dependency>
             <groupId>com.fasterxml.jackson.jaxrs</groupId>
             <artifactId>jackson-jaxrs-json-provider</artifactId>
-            <version>${jackson.version}</version>
+            <version>${jackson.version}.1</version>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
index bf913f45f6bcbe9ab62c36a2f61f440407ef4b37..b63b130bb1cb10f4d9e09c0781280cd08455060f 100644
--- a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
+++ b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
@@ -1051,6 +1051,7 @@ public class BaseSecurityManager implements BaseSecurity, UserDataDeletable {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select auth from ").append(AuthenticationImpl.class.getName()).append(" as auth")
 		  .append(" inner join fetch auth.identity ident")
+		  .append(" inner join fetch ident.user identUser")
 		  .append(" where auth.provider=:provider and auth.authusername=:authusername");
 
 		List<Authentication> results = dbInstance.getCurrentEntityManager()
@@ -1070,6 +1071,7 @@ public class BaseSecurityManager implements BaseSecurity, UserDataDeletable {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select auth from ").append(AuthenticationImpl.class.getName()).append(" as auth")
 		  .append(" inner join fetch auth.identity ident")
+		  .append(" inner join fetch ident.user identUser")
 		  .append(" where auth.provider in (:providers) and auth.authusername=:authusername");
 		return dbInstance.getCurrentEntityManager()
 				.createQuery(sb.toString(), Authentication.class)
diff --git a/src/main/java/org/olat/commons/calendar/ICalServlet.java b/src/main/java/org/olat/commons/calendar/ICalServlet.java
index e33d5d4385578f086a3ff36fa43df1d0bccb9567..4bbaad56da8018d45b3e04e78b5f0ef6b6200345 100644
--- a/src/main/java/org/olat/commons/calendar/ICalServlet.java
+++ b/src/main/java/org/olat/commons/calendar/ICalServlet.java
@@ -343,7 +343,7 @@ public class ICalServlet extends HttpServlet {
 		String userAgent = request.getHeader("User-Agent");
 		if(userAgent == null) {
 			return Agent.unkown;
-		} else if(userAgent.indexOf("Microsoft Outlook") >= 0 || userAgent.indexOf("Microsoft Office") >= 0
+		} else if(userAgent.indexOf("Microsoft ") >= 0 // to catch "Microsoft Outlook", "Microsoft Office", "Microsoft Exchange" which are all user agents used by outlook.com
 				|| userAgent.equals("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)")) {// <- this is the user agent of Outlook live
 			return Agent.outlook;
 		} else if(userAgent.indexOf("Google") >= 0 && userAgent.indexOf("Calendar") >= 0) {
diff --git a/src/main/java/org/olat/core/commons/services/vfs/manager/VFSRevisionDAO.java b/src/main/java/org/olat/core/commons/services/vfs/manager/VFSRevisionDAO.java
index 1cbd4504c172205c2dd307b96b9d3777be1838d3..bd5242efc79f8dd3ac081d6b08685ecba8fe8242 100644
--- a/src/main/java/org/olat/core/commons/services/vfs/manager/VFSRevisionDAO.java
+++ b/src/main/java/org/olat/core/commons/services/vfs/manager/VFSRevisionDAO.java
@@ -255,13 +255,13 @@ public class VFSRevisionDAO {
 		if(locked != null) {
 			qb.where().append("metadata.locked=:locked");
 		}
-		if(downloadCount > 0) {
+		if(downloadCount != null && downloadCount.longValue() > 0) {
 			qb.where().append("metadata.downloadCount>=:downloadCount");
 		}
-		if(revisionCount > 0) {
+		if(revisionCount != null && revisionCount.longValue() > 0) {
 			qb.where().append("metadata.revisionNr>=:revisionCount");
 		}
-		if(size > 0) {
+		if(size != null && size.intValue() > 0) {
 			qb.where().append("rev.size>=:size");
 		}
 
@@ -295,13 +295,13 @@ public class VFSRevisionDAO {
 		if(locked != null) {
 			query.setParameter("locked", locked);
 		}
-		if(downloadCount > 0) {
+		if(downloadCount != null && downloadCount.longValue() > 0) {
 			query.setParameter("downloadCount", downloadCount);
 		}
-		if(revisionCount > 0) {
+		if(revisionCount != null && revisionCount.longValue() > 0) {
 			query.setParameter("revisionCount", revisionCount);
 		}
-		if(size > 0) {
+		if(size != null && size.intValue() > 0) {
 			query.setParameter("size", Long.valueOf(size));
 		}
 		
diff --git a/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java b/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java
index a80d382a4df557e4f191200184ab87ff75984edb..8d2065831532f7724343432cc50f9a57f7a37f43 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java
+++ b/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java
@@ -70,7 +70,9 @@ public class WebDAVModule extends AbstractSpringModule implements ConfigOnOff {
 	private boolean prependCourseReferenceToTitle;
 	@Value("${webdav.basic.authentication.black.list}")
 	private String basicAuthenticationBlackList;
-
+	@Value("${webdav.user.agent.black.list}")
+	private String userAgentBlackList;
+	
 	@Value("${webdav.learners.bookmarks.enabled:true}")
 	private boolean enableLearnersBookmarksCourse;
 	/**
@@ -233,6 +235,21 @@ public class WebDAVModule extends AbstractSpringModule implements ConfigOnOff {
 		this.basicAuthenticationBlackList = basicAuthenticationBlackList;
 	}
 
+	public String[] getUserAgentBlackListArray() {
+		if(StringHelper.containsNonWhitespace(userAgentBlackList)) {
+			return userAgentBlackList.split("[,]");
+		}
+		return new String[0];
+	}
+
+	public String getUserAgentBlackList() {
+		return userAgentBlackList;
+	}
+
+	public void setUserAgentBlackList(String userAgentBlackList) {
+		this.userAgentBlackList = userAgentBlackList;
+	}
+
 	/**
 	 * Return an unmodifiable map
 	 * @return
diff --git a/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerImpl.java b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerImpl.java
index b9502df765c8f636d28f43fdbb39d932faec3013..f256e9d121af3b25ad15d587775510a6bddf9bff 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerImpl.java
+++ b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerImpl.java
@@ -293,7 +293,7 @@ public class WebDAVManagerImpl implements WebDAVManager, InitializingBean {
 
 	protected UserSession handleDigestAuthentication(DigestAuthentication digestAuth, HttpServletRequest request) {
 		Identity identity = webDAVAuthManager.digestAuthentication(request.getMethod(), digestAuth);
-		if(identity != null) {
+		if(identity != null && securityManager.isIdentityVisible(identity)) {
 			log.info("WebDAV Digest authentication of: {}", identity);
 			return afterAuthorization(identity, request);
 		}
@@ -315,7 +315,7 @@ public class WebDAVManagerImpl implements WebDAVManager, InitializingBean {
 			// In this example, we simply check
 			// that neither field is blank
 			Identity identity = webDAVAuthManager.authenticate(null, userID, password);
-			if (identity != null) {
+			if (identity != null && securityManager.isIdentityVisible(identity)) {
 				log.debug("WebDAV Basic authentication of: {}", identity);
 				return afterAuthorization(identity, request);
 			}
diff --git a/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java b/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java
index 03a7820cee2e0e5da9c93a8256d30063851ad4ba..cad3154c7b23d35d171de702e3dd845db8604216 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java
+++ b/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java
@@ -54,9 +54,11 @@ import org.olat.core.commons.services.webdav.WebDAVDispatcher;
 import org.olat.core.commons.services.webdav.WebDAVManager;
 import org.olat.core.commons.services.webdav.WebDAVModule;
 import org.olat.core.dispatcher.Dispatcher;
+import org.olat.core.gui.media.ServletUtil;
 import org.olat.core.helpers.Settings;
 import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.UserSession;
 import org.olat.core.util.vfs.QuotaExceededException;
 import org.olat.core.util.vfs.VFSItem;
@@ -273,7 +275,7 @@ public class WebDAVDispatcherImpl
 	throws ServletException, IOException {
 		if (webDAVManager == null) {
 			resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
-		} else if(webDAVModule == null || !webDAVModule.isEnabled()) {
+		} else if(webDAVModule == null || !webDAVModule.isEnabled() || isUserAgentExcluded(req)) {
 			resp.setStatus(WebdavStatus.SC_FORBIDDEN);
 		} else if (webDAVManager.handleAuthentication(req, resp)) {
 			webdavService(req, resp);
@@ -281,6 +283,21 @@ public class WebDAVDispatcherImpl
 			//the method handleAuthentication will send the challenges for authentication
 		}
 	}
+	
+	private boolean isUserAgentExcluded(HttpServletRequest req) {
+		String userAgent = ServletUtil.getUserAgent(req);
+		if(!StringHelper.containsNonWhitespace(userAgent)) {
+			userAgent = "";
+		}
+		String[] blackList = webDAVModule.getUserAgentBlackListArray();
+		for(String blackListedAgent:blackList) {
+			if((blackListedAgent.length() < 2 && userAgent.equalsIgnoreCase(blackListedAgent))
+					|| (blackListedAgent.length() >= 2 && userAgent.contains(blackListedAgent))) {
+				return true;
+			}
+		}
+		return false;
+	}
 
 	/**
      * Handles the special WebDAV methods.
diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java b/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java
index 457f814f10773b80f20a3804872de8a77ee6c00b..37ad1d594cec3b2cdfd34262ce0af392ac4611c9 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java
+++ b/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java
@@ -19,16 +19,20 @@
  */
 package org.olat.core.commons.services.webdav.ui;
 
-import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.services.webdav.WebDAVModule;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
+import org.olat.core.gui.components.form.flexible.elements.SpacerElement;
+import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.core.util.StringHelper;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -39,6 +43,8 @@ public class WebDAVAdminController extends FormBasicController {
 	
 	private static final String[] onKeys = new String[]{"xx"};
 	
+	private TextElement excludeUserAgentsClientsEl;
+	private MultipleSelectionElement excludeClientsEl;
 	private MultipleSelectionElement enableModuleEl;
 	private MultipleSelectionElement enableLinkEl;
 	private MultipleSelectionElement enableDigestEl;
@@ -48,13 +54,17 @@ public class WebDAVAdminController extends FormBasicController {
 	private MultipleSelectionElement learnersAsParticipantEl;
 	private MultipleSelectionElement learnersBookmarkEl;
 	private MultipleSelectionElement prependReferenceEl;
+	private SpacerElement spacer1;
+	private SpacerElement spacer2;
 	
-	private final WebDAVModule webDAVModule;
+
+	@Autowired
+	private WebDAVModule webDAVModule;
 	
 	public WebDAVAdminController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
-		webDAVModule = CoreSpringFactory.getImpl(WebDAVModule.class);
 		initForm(ureq);
+		updateEnabledDisabled();
 	}
 
 	@Override
@@ -64,56 +74,51 @@ public class WebDAVAdminController extends FormBasicController {
 		setFormDescription("admin.webdav.description");
 		setFormContextHelp("WebDAV");
 
-
 		boolean enabled = webDAVModule.isEnabled();
 		String[] values = new String[] { getTranslator().translate("webdav.on") };
 		enableModuleEl = uifactory.addCheckboxesHorizontal("webdavModule", "webdav.module", formLayout, onKeys, values);
-		enableModuleEl.select("xx", enabled);
 		enableModuleEl.addActionListener(FormEvent.ONCHANGE);
+		enableModuleEl.select("xx", enabled);
 		
 		enableLinkEl = uifactory.addCheckboxesHorizontal("webdavLink", "webdav.link", formLayout, onKeys, values);
 		enableLinkEl.select("xx", webDAVModule.isLinkEnabled());
-		enableLinkEl.addActionListener(FormEvent.ONCHANGE);
-		enableLinkEl.setEnabled(enabled);
 		
 		enableDigestEl = uifactory.addCheckboxesHorizontal("webdavDigest", "webdav.digest", formLayout, onKeys, values);
 		enableDigestEl.select("xx", webDAVModule.isDigestAuthenticationEnabled());
-		enableDigestEl.addActionListener(FormEvent.ONCHANGE);
-		enableDigestEl.setEnabled(enabled);
+
+		String excludedUserAgents = webDAVModule.getUserAgentBlackList();
+		excludeClientsEl = uifactory.addCheckboxesHorizontal("webdavExclusion", "webdav.client.exclusion", formLayout, onKeys, values);
+		excludeClientsEl.select("xx", StringHelper.containsNonWhitespace(excludedUserAgents));
+		excludeClientsEl.addActionListener(FormEvent.ONCHANGE);
+		
+		excludeUserAgentsClientsEl = uifactory.addTextElement("webdav.user.agent.exclusion", 4096, excludedUserAgents, formLayout);
+		excludeUserAgentsClientsEl.setVisible(excludeClientsEl.isAtLeastSelected(1));
 		
-		uifactory.addSpacerElement("spacer1", formLayout, false);
+		spacer1 = uifactory.addSpacerElement("spacer1", formLayout, false);
 		
 		enableTermsFoldersEl = uifactory.addCheckboxesHorizontal("webdavTermsFolders", "webdav.termsfolders", formLayout, onKeys, values);
 		enableTermsFoldersEl.select("xx", webDAVModule.isTermsFoldersEnabled());
-		enableTermsFoldersEl.addActionListener(FormEvent.ONCHANGE);
-		enableTermsFoldersEl.setEnabled(enabled);
 		
 		enableCurriculumElementFoldersEl = uifactory.addCheckboxesHorizontal("webdavCurriculumsElementsFolders", "webdav.curriculumelementsfolders", formLayout, onKeys, values);
 		enableCurriculumElementFoldersEl.select("xx", webDAVModule.isCurriculumElementFoldersEnabled());
-		enableCurriculumElementFoldersEl.addActionListener(FormEvent.ONCHANGE);
-		enableCurriculumElementFoldersEl.setEnabled(enabled);
 		
 		enableManagedFoldersEl = uifactory.addCheckboxesHorizontal("webdavManagedFolders", "webdav.managedfolders", formLayout, onKeys, values);
 		enableManagedFoldersEl.select("xx", webDAVModule.isManagedFoldersEnabled());
-		enableManagedFoldersEl.addActionListener(FormEvent.ONCHANGE);
-		enableManagedFoldersEl.setEnabled(enabled);
 		
 		prependReferenceEl = uifactory.addCheckboxesHorizontal("webdavPrepend", "webdav.prepend.reference", formLayout, onKeys, values);
 		prependReferenceEl.select("xx", webDAVModule.isPrependCourseReferenceToTitle());
-		prependReferenceEl.addActionListener(FormEvent.ONCHANGE);
-		prependReferenceEl.setEnabled(enabled);
-
-		uifactory.addSpacerElement("spacer2", formLayout, false);
+		
+		spacer2 = uifactory.addSpacerElement("spacer2", formLayout, false);
 		
 		learnersAsParticipantEl = uifactory.addCheckboxesHorizontal("learnersParticipants", "webdav.for.learners.participants", formLayout, onKeys, values);
 		learnersAsParticipantEl.select("xx", webDAVModule.isEnableLearnersParticipatingCourses());
-		learnersAsParticipantEl.addActionListener(FormEvent.ONCHANGE);
-		learnersAsParticipantEl.setEnabled(enabled);
 		
 		learnersBookmarkEl = uifactory.addCheckboxesHorizontal("learnerBookmarks", "webdav.for.learners.bookmarks", formLayout, onKeys, values);
 		learnersBookmarkEl.select("xx", webDAVModule.isEnableLearnersBookmarksCourse());
-		learnersBookmarkEl.addActionListener(FormEvent.ONCHANGE);
-		learnersBookmarkEl.setEnabled(enabled);
+		
+		FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
+		formLayout.add(buttonsCont);
+		uifactory.addFormSubmitButton("save", buttonsCont);
 	}
 
 	@Override
@@ -126,41 +131,44 @@ public class WebDAVAdminController extends FormBasicController {
 		if(source == enableModuleEl) {
 			boolean enabled = enableModuleEl.isAtLeastSelected(1);
 			webDAVModule.setEnabled(enabled);
-			enableLinkEl.setEnabled(enabled);
-			enableDigestEl.setEnabled(enabled);
-			enableTermsFoldersEl.setEnabled(enabled);
-			learnersAsParticipantEl.setEnabled(enabled);
-			learnersBookmarkEl.setEnabled(enabled);
-		} else if(source == enableLinkEl) {
-			boolean enabled = enableLinkEl.isAtLeastSelected(1);
-			webDAVModule.setLinkEnabled(enabled);
-		} else if(source == enableDigestEl) {
-			boolean enabled = enableDigestEl.isAtLeastSelected(1);
-			webDAVModule.setDigestAuthenticationEnabled(enabled);
-		} else if(source == enableTermsFoldersEl) {
-			boolean enabled = enableTermsFoldersEl.isAtLeastSelected(1);
-			webDAVModule.setTermsFoldersEnabled(enabled);
-		} else if(source == enableCurriculumElementFoldersEl) {
-			boolean enabled = enableCurriculumElementFoldersEl.isAtLeastSelected(1);
-			webDAVModule.setCurriculumElementFoldersEnabled(enabled);
-		} else if(source == learnersAsParticipantEl) {
-			boolean enabled = learnersAsParticipantEl.isAtLeastSelected(1);
-			webDAVModule.setEnableLearnersParticipatingCourses(enabled);
-		} else if(source == learnersBookmarkEl) {
-			boolean enabled = learnersBookmarkEl.isAtLeastSelected(1);
-			webDAVModule.setEnableLearnersBookmarksCourse(enabled);
-		} else if(source == prependReferenceEl) {
-			boolean enabled = prependReferenceEl.isAtLeastSelected(1);
-			webDAVModule.setPrependCourseReferenceToTitle(enabled);
-		} else if(source == enableManagedFoldersEl) {
-			boolean enabled = enableManagedFoldersEl.isAtLeastSelected(1);
-			webDAVModule.setManagedFoldersEnabled(enabled);
+			updateEnabledDisabled();
+		} else if(source == excludeClientsEl) {
+			excludeUserAgentsClientsEl.setVisible(excludeClientsEl.isAtLeastSelected(1));
 		}
 		super.formInnerEvent(ureq, source, event);
 	}
+	
+	private void updateEnabledDisabled() {
+		boolean enabled = enableModuleEl.isAtLeastSelected(1);
+		
+		enableLinkEl.setVisible(enabled);
+		enableDigestEl.setVisible(enabled);
+		enableTermsFoldersEl.setVisible(enabled);
+		learnersAsParticipantEl.setVisible(enabled);
+		learnersBookmarkEl.setVisible(enabled);
+		enableCurriculumElementFoldersEl.setVisible(enabled);
+		enableManagedFoldersEl.setVisible(enabled);
+		prependReferenceEl.setVisible(enabled);
+		excludeClientsEl.setVisible(enabled);
+		excludeUserAgentsClientsEl.setVisible(enabled && excludeClientsEl.isAtLeastSelected(1));
+		spacer1.setVisible(enabled);
+		spacer2.setVisible(enabled);
+	}
 
 	@Override
 	protected void formOK(UserRequest ureq) {
-		//
+		webDAVModule.setLinkEnabled(enableLinkEl.isAtLeastSelected(1));
+		webDAVModule.setDigestAuthenticationEnabled(enableDigestEl.isAtLeastSelected(1));
+		webDAVModule.setTermsFoldersEnabled(enableTermsFoldersEl.isAtLeastSelected(1));
+		webDAVModule.setCurriculumElementFoldersEnabled(enableCurriculumElementFoldersEl.isAtLeastSelected(1));
+		webDAVModule.setEnableLearnersParticipatingCourses(learnersAsParticipantEl.isAtLeastSelected(1));
+		webDAVModule.setEnableLearnersBookmarksCourse(learnersBookmarkEl.isAtLeastSelected(1));
+		webDAVModule.setPrependCourseReferenceToTitle(prependReferenceEl.isAtLeastSelected(1));
+		webDAVModule.setManagedFoldersEnabled(enableManagedFoldersEl.isAtLeastSelected(1));
+		if(excludeClientsEl.isAtLeastSelected(1)) {
+			webDAVModule.setUserAgentBlackList(excludeUserAgentsClientsEl.getValue());
+		} else {
+			webDAVModule.setUserAgentBlackList(null);
+		}
 	}
 }
diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties
index e081425ac73199d655d8f42795193eea0db1895b..97cd86527ad9d4c263a812229ad028d1b7a1503e 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties
@@ -3,6 +3,7 @@ admin.menu.title=WebDAV
 admin.menu.title.alt=WebDAV Zugang
 admin.webdav.description=Mit Hilfe von WebDAV k\u00F6nnen Sie OpenOlat Ordner auf Ihrem lokalen Desktop wie lokale Ordner anzeigen und verwenden. Konfigurieren Sie ob diese Funktion allen Benutzern Systemweit zur Verf\u00FCgung stehen soll. Bitte lesen sie die Kontexthilfe.
 core.webdav=WebDAV
+webdav.client.exclusion=WebDAV Client Verbot
 webdav.curriculumelementsfolders=Kurse nach Curriculumelementen gruppieren
 webdav.digest=Digest Authentication bei HTTP Zugang verwenden 
 webdav.for.learners.bookmarks=Zugriff f\u00FCr Studenten / Betreuer Favoriten
@@ -13,3 +14,4 @@ webdav.module=WebDAV Zugang
 webdav.on=ein
 webdav.prepend.reference=Kennzeichen dem Titel voranstellen
 webdav.termsfolders=Kurse nach Semesterdaten gruppieren
+webdav.user.agent.exclusion=Liste von User-Agent (Komma als Trenzeichen)
diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties
index a4a726fe0211c2ab0ffc5930452415130b39a804..28fe7f470a79cd039b51795fc3d4f1139b2d47f1 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties
@@ -3,6 +3,7 @@ admin.menu.title=WebDAV
 admin.menu.title.alt=WebDAV access
 admin.webdav.description=Using WebDAV you can mount and use OpenOlat folders on your local desktop as if they were local folders. Enable this feature to make it accessable to all users of your platform. Please read the context help.
 core.webdav=WebDAV
+webdav.client.exclusion=WebDAV Client exclusion
 webdav.curriculumelementsfolders=Group courses by curriculum elements
 webdav.digest=Digest Authentication for HTTP access
 webdav.for.learners.bookmarks=Enable access for courses that users marked as favorite
@@ -13,3 +14,4 @@ webdav.module=WebDAV access
 webdav.on=enabled
 webdav.prepend.reference=Prepend external course reference to title
 webdav.termsfolders=Group courses by semester terms
+webdav.user.agent.exclusion=List of User-Agents (comma as separator)
diff --git a/src/main/java/org/olat/login/auth/OLATAuthManager.java b/src/main/java/org/olat/login/auth/OLATAuthManager.java
index 49b08053b35968e2293588411b71ce14f58cced7..77050a7dc6b961252009352578e63f71082f92fe 100644
--- a/src/main/java/org/olat/login/auth/OLATAuthManager.java
+++ b/src/main/java/org/olat/login/auth/OLATAuthManager.java
@@ -125,7 +125,7 @@ public class OLATAuthManager implements AuthenticationSPI {
 					if(identities.size() == 1) {
 						ident = identities.get(0);
 					} else if(identities.size() > 1) {
-						log.error("more than one identity found with email::" + login);
+						log.error("more than one identity found with email::{}", login);
 					}
 					
 					if (ident == null) {
@@ -144,7 +144,7 @@ public class OLATAuthManager implements AuthenticationSPI {
 		}
 
 		if (authentication == null) {
-			log.info(Tracing.M_AUDIT, "Cannot authenticate user " + login + " via provider OLAT");
+			log.info(Tracing.M_AUDIT, "Cannot authenticate user {} via provider OLAT", login);
 			return null;
 		}
 		
@@ -156,12 +156,15 @@ public class OLATAuthManager implements AuthenticationSPI {
 				authentication = securityManager.updateCredentials(authentication, password, defAlgorithm);
 			}
 			Identity identity = authentication.getIdentity();
+			if(!securityManager.isIdentityVisible(identity)) {
+				return null;
+			}
 			if(identity != null && webDAVAuthManager != null) {
 				webDAVAuthManager.upgradePassword(identity, login, password);
 			}
 			return identity;
 		}
-		log.info(Tracing.M_AUDIT, "Cannot authenticate user " + login + " via provider OLAT");
+		log.info(Tracing.M_AUDIT, "Cannot authenticate user {} via provider OLAT", login);
 		return null;
 	}
 	
@@ -242,7 +245,7 @@ public class OLATAuthManager implements AuthenticationSPI {
 			if(ldapLoginModule.isPropagatePasswordChangedOnLdapServer()) {
 				LDAPError ldapError = new LDAPError();
 				ldapLoginManager.changePassword(identity, newPwd, ldapError);
-				log.info(Tracing.M_AUDIT, doer.getKey() + " change the password on the LDAP server for identity: " + identity.getKey());
+				log.info(Tracing.M_AUDIT, "{} change the password on the LDAP server for identity: {}", doer.getKey(), identity.getKey());
 				allOk = ldapError.isEmpty();
 
 				if(allOk && ldapLoginModule.isCacheLDAPPwdAsOLATPwdOnLogin()) {
@@ -301,10 +304,10 @@ public class OLATAuthManager implements AuthenticationSPI {
 		Authentication auth = securityManager.findAuthentication(identity, "OLAT");
 		if (auth == null) { // create new authentication for provider OLAT
 			securityManager.createAndPersistAuthentication(identity, "OLAT", identity.getName(), newPwd, loginModule.getDefaultHashAlgorithm());
-			log.info(Tracing.M_AUDIT, doer.getKey() + " created new authenticatin for identity: " + identity.getKey());
+			log.info(Tracing.M_AUDIT, "{} created new authenticatin for identity: {}", doer.getKey(), identity.getKey());
 		} else {
 			securityManager.updateCredentials(auth, newPwd, loginModule.getDefaultHashAlgorithm());
-			log.info(Tracing.M_AUDIT, doer.getKey() + " set new password for identity: " + identity.getKey());
+			log.info(Tracing.M_AUDIT, "{} set new password for identity: {}", doer.getKey(),  identity.getKey());
 		}
 		
 		if(StringHelper.containsNonWhitespace(username) && webDAVAuthManager != null) {
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index da09762d02e735cfe3893738d9836d3f167d8671..c90fb1942404a432147f954c5ff5643d79f2111d 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -566,6 +566,8 @@ auth.digest.enabled=true
 webdav.termsfolders.enabled=true
 # User agents for which the basic authentication should never be proposed
 webdav.basic.authentication.black.list=Microsoft Office Excel,Microsoft Excel,Microsoft-WebDAV-MiniRedir
+# User agents which don't play nice
+webdav.user.agent.black.list=-
 
 ########################################################################
 # Image and PDF scale/thumbnail options
diff --git a/src/test/java/org/olat/basesecurity/GetIdentitiesByPowerSearchTest.java b/src/test/java/org/olat/basesecurity/GetIdentitiesByPowerSearchTest.java
index 4cda8b7182a980a1fb2afe215ce114f02e0e332e..6081edf2f0a978734d8651841dd6b723267aa591 100644
--- a/src/test/java/org/olat/basesecurity/GetIdentitiesByPowerSearchTest.java
+++ b/src/test/java/org/olat/basesecurity/GetIdentitiesByPowerSearchTest.java
@@ -82,17 +82,21 @@ public class GetIdentitiesByPowerSearchTest extends OlatTestCase {
 		
 		// basic query to find all system users without restrictions
 		List<Identity> results = baseSecurityManager.getIdentitiesByPowerSearch(null, null, true, null, null, null, null, null, null, null);
-		assertTrue(results.size()>0); 
+		Assert.assertFalse(results.isEmpty()); 
 		int numberOfAllUsers = results.size();
 		
 		results = baseSecurityManager.getIdentitiesByPowerSearch(null, null, true, null, null, null, null, null, null,Identity.STATUS_ACTIV);
-		assertTrue(results.size()>0);
+		Assert.assertFalse(results.isEmpty());
 		int numberOfActiveUsers = results.size();
 		
 		results = baseSecurityManager.getIdentitiesByPowerSearch(null, null, true, null, null, null, null, null, null, Identity.STATUS_DELETED);
-		assertTrue(results.size() >0);
+		Assert.assertFalse(results.isEmpty());
 		int numberOfDeletedUsers = results.size();
-		assertEquals("Number of all users != activeUsers + deletedUsers" , numberOfAllUsers, numberOfActiveUsers + numberOfDeletedUsers);
+		
+		results = baseSecurityManager.getIdentitiesByPowerSearch(null, null, true, null, null, null, null, null, null,Identity.STATUS_LOGIN_DENIED);
+		Assert.assertNotNull(results);
+		int numberOfDeniedUsers = results.size();
+		assertEquals("Number of all users != activeUsers + deletedUsers + loginDeniedUsers" , numberOfAllUsers, numberOfActiveUsers + numberOfDeletedUsers + numberOfDeniedUsers);
 		
 		// user attributes search test
 		dbInstance.commitAndCloseSession();
@@ -603,6 +607,12 @@ public class GetIdentitiesByPowerSearchTest extends OlatTestCase {
 			Assert.assertEquals(Identity.STATUS_DELETED, deletedIdentity.getStatus());
 		}
 		int numberOfDeletedUsers = deletedIdentities.size();
+		
+		List<Identity> deniedIdentities = baseSecurityManager.getIdentitiesByPowerSearch(null, null, true, null, null, null, null, null, null, Identity.STATUS_LOGIN_DENIED);
+		for(Identity deniedIdentity:deniedIdentities) {
+			Assert.assertEquals(Identity.STATUS_LOGIN_DENIED, deniedIdentity.getStatus());
+		}
+		int numberOfDeniedUsers = deniedIdentities.size();
 
 		Date createdAfter = before;
 		Date createdBefore = after;
@@ -610,17 +620,17 @@ public class GetIdentitiesByPowerSearchTest extends OlatTestCase {
 		assertEquals("Search with date (createdAfter,createdBefore) delivers not the same number of users", numberOfAllUsers, results.size());
 
 		results = baseSecurityManager.getVisibleIdentitiesByPowerSearch(null, null, true, null, null, before, after);
-		assertEquals("Search (visible identities) with date (createdAfter,createdBefore) delivers not the same number of users", (numberOfAllUsers - numberOfDeletedUsers) , results.size()); // One identity is deleted
+		assertEquals("Search (visible identities) with date (createdAfter,createdBefore) delivers not the same number of users", (numberOfAllUsers - numberOfDeletedUsers - numberOfDeniedUsers) , results.size()); // One identity is deleted
 
 		results = baseSecurityManager.getIdentitiesByPowerSearch(null, null, true, null, null, null, after, null, null, null);
 		assertEquals("Search with date (only after) delivers not the same number of users", numberOfAllUsers, results.size());
 		results = baseSecurityManager.getVisibleIdentitiesByPowerSearch(null, null, true, null, null, null, after);
-		assertEquals("Search (visible identities) with date (createdAfter,createdBefore) delivers not the same number of users", (numberOfAllUsers - numberOfDeletedUsers) , results.size()); // One identity is deleted
+		assertEquals("Search (visible identities) with date (createdAfter,createdBefore) delivers not the same number of users", (numberOfAllUsers - numberOfDeletedUsers - numberOfDeniedUsers) , results.size()); // One identity is deleted
 
 		results = baseSecurityManager.getIdentitiesByPowerSearch(null, null, true, null, null, before, null, null, null, null);
 		assertEquals("Search with date (only before) delivers not the same number of users", numberOfAllUsers, results.size());
 		results = baseSecurityManager.getVisibleIdentitiesByPowerSearch(null, null, true, null, null, before, null);
-		assertEquals("Search (visible identities) with date (createdAfter,createdBefore) delivers not the same number of users", (numberOfAllUsers - numberOfDeletedUsers) , results.size()); // One identity is deleted
+		assertEquals("Search (visible identities) with date (createdAfter,createdBefore) delivers not the same number of users", (numberOfAllUsers - numberOfDeletedUsers - numberOfDeniedUsers) , results.size()); // One identity is deleted
 
 		results = baseSecurityManager.getIdentitiesByPowerSearch(null, null, true, null, null, after, before, null, null, null);
 		assertTrue(results.size() == 0);
diff --git a/src/test/java/org/olat/core/commons/services/vfs/manager/VFSRevisionDAOTest.java b/src/test/java/org/olat/core/commons/services/vfs/manager/VFSRevisionDAOTest.java
index 47acbafb5a31c8d38b8df09fb370a433fe81146a..139a036f2aefad62b60b0d4d0edab0960ee75a83 100644
--- a/src/test/java/org/olat/core/commons/services/vfs/manager/VFSRevisionDAOTest.java
+++ b/src/test/java/org/olat/core/commons/services/vfs/manager/VFSRevisionDAOTest.java
@@ -19,8 +19,8 @@
  */
 package org.olat.core.commons.services.vfs.manager;
 
-import java.time.ZonedDateTime;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
@@ -225,7 +225,7 @@ public class VFSRevisionDAOTest extends OlatTestCase {
 	
 	@Test
 	public void getLargest() {
-		Date fiveMinutesInThePast = Date.from(ZonedDateTime.now().minusMinutes(5).toInstant());
+		Date fiveMinutesInThePast = addMinutesToDate(-5, new Date());
 		
 		Identity author = JunitTestHelper.createAndPersistIdentityAsRndUser("rev-1");
 		VFSMetadata metadata1 = vfsMetadataDao.createMetadata(UUID.randomUUID().toString(), "test/revs", "text1.txt",
@@ -243,12 +243,12 @@ public class VFSRevisionDAOTest extends OlatTestCase {
 		Assert.assertNotNull(revision3);
 		
 		int maxResult = 100;
-		Date createdAtNewer = Date.from(ZonedDateTime.now().minusMonths(10).toInstant());
-		Date createdAtOlder = Date.from(ZonedDateTime.now().toInstant());
-		Date editedAtNewer = Date.from(ZonedDateTime.now().minusMonths(10).toInstant());
-		Date editedAtOlder = Date.from(ZonedDateTime.now().toInstant());
+		Date createdAtNewer = addMinutesToDate(-150, new Date());
+		Date createdAtOlder = addMinutesToDate(5, new Date());
+		Date editedAtNewer = addMinutesToDate(-150, new Date());
+		Date editedAtOlder = addMinutesToDate(5, new Date());
 		
-		List<VFSRevision> queryResult = revisionDao.getLargest(maxResult, createdAtNewer, createdAtOlder, editedAtNewer, editedAtOlder, null, null, null, null, 0, Long.valueOf(0), 0);
+		List<VFSRevision> queryResult = revisionDao.getLargest(maxResult, createdAtNewer, createdAtOlder, editedAtNewer, editedAtOlder, null, null, null, null, null, null, null);
 		
 		Assert.assertNotNull(queryResult);
 		Assert.assertTrue(queryResult.size() > 0);
@@ -260,4 +260,33 @@ public class VFSRevisionDAOTest extends OlatTestCase {
 			Assert.assertTrue(vfsMetadata.getFileLastModified().compareTo(editedAtOlder) <= 0);
 		}
 	}
+	
+	/**
+	 * Only check the query syntax
+	 */
+	@Test
+	public void getLargest_allParameters() {
+
+		Date now = new Date();
+		
+		Identity author = JunitTestHelper.createAndPersistIdentityAsRndUser("rev-1");
+		VFSMetadata metadata = vfsMetadataDao.createMetadata(UUID.randomUUID().toString(), "test/revs", "text_all.txt",
+				new Date(), 10000l, false, "file:///text.tx", "file", null);
+		VFSRevision revision = revisionDao.createRevision(author, "._oo_vr_all_text.txt", 1, 25l, now, "A comment", metadata);
+		dbInstance.commitAndCloseSession();
+		Assert.assertNotNull(revision);
+
+		List<VFSRevision> queryResult = revisionDao.getLargest(100, now, now, now, now, now, now,
+				Boolean.TRUE, Boolean.FALSE, Integer.valueOf(25), Long.valueOf(33), Integer.valueOf(55));
+		
+		Assert.assertNotNull(queryResult);
+	}
+	
+	private Date addMinutesToDate(int minutes, Date date) {
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		cal.add(Calendar.MINUTE, minutes);
+		return cal.getTime();
+	}
+	
 }
diff --git a/src/test/java/org/olat/core/commons/services/vfs/manager/VFSStatsDAOTest.java b/src/test/java/org/olat/core/commons/services/vfs/manager/VFSStatsDAOTest.java
index 013d2587f9f61eee02054d17ef83f78af6f5a8f8..03fa7c1a46cec56d93c2b83ad35ae3f22c941010 100644
--- a/src/test/java/org/olat/core/commons/services/vfs/manager/VFSStatsDAOTest.java
+++ b/src/test/java/org/olat/core/commons/services/vfs/manager/VFSStatsDAOTest.java
@@ -42,10 +42,10 @@ public class VFSStatsDAOTest extends OlatTestCase {
 	public void getFileStats() {
 		VFSFileStatistics fileStatistics = vfsStatsDAO.getFileStats();
 		
-		Assert.assertTrue(fileStatistics.getFilesAmount() > 0);
-		Assert.assertTrue(fileStatistics.getFilesSize() > 0);
-		Assert.assertTrue(fileStatistics.getTrashAmount() > 0);
-		Assert.assertTrue(fileStatistics.getTrashSize() > 0);
+		Assert.assertTrue(fileStatistics.getFilesAmount() >= 0);
+		Assert.assertTrue(fileStatistics.getFilesSize() >= 0);
+		Assert.assertTrue(fileStatistics.getTrashAmount() >= 0);
+		Assert.assertTrue(fileStatistics.getTrashSize() >= 0);
 	}
 	
 	@Test
diff --git a/src/test/java/org/olat/core/commons/services/webdav/manager/WebDAVAuthManagerTest.java b/src/test/java/org/olat/core/commons/services/webdav/manager/WebDAVAuthManagerTest.java
index 87d4e1f2d2beb6e277639dbc37d64c1ea711ebc0..733054b8af93f9e843d9f639d7648b1b4239923b 100644
--- a/src/test/java/org/olat/core/commons/services/webdav/manager/WebDAVAuthManagerTest.java
+++ b/src/test/java/org/olat/core/commons/services/webdav/manager/WebDAVAuthManagerTest.java
@@ -50,6 +50,8 @@ public class WebDAVAuthManagerTest extends OlatTestCase {
 	@Autowired
 	private UserManager userManager;
 	@Autowired
+	private OLATAuthManager authManager;
+	@Autowired
 	private BaseSecurity securityManager;
 	@Autowired
 	private WebDAVAuthManager webdavAuthManager;
@@ -154,4 +156,49 @@ public class WebDAVAuthManagerTest extends OlatTestCase {
 		Assert.assertNotNull(id2);
 		dbInstance.commit();
 	}
+	
+	@Test
+	public void authenticationByName() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("webdav-user-1");
+		Identity reloadedUser = authManager.authenticate(id, id.getName(), JunitTestHelper.PWD);
+		Assert.assertNotNull(reloadedUser);
+		dbInstance.commitAndCloseSession();
+
+		// login successful
+		Identity authenticatedByLogin = webdavAuthManager.authenticate(null, id.getName(), JunitTestHelper.PWD);
+		Assert.assertNotNull(authenticatedByLogin);
+		Assert.assertEquals(id, authenticatedByLogin);
+	}
+	
+	@Test
+	public void authenticationByName_failed() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("webdav-usser-2");
+		Identity reloadedUser = authManager.authenticate(id, id.getName(), JunitTestHelper.PWD);
+		Assert.assertNotNull(reloadedUser);
+		dbInstance.commitAndCloseSession();
+		
+		// login successful
+		Identity authenticatedId = webdavAuthManager.authenticate(null, id.getName(), "ooops");
+		Assert.assertNull(authenticatedId);
+	}
+	
+	@Test
+	public void authenticationByName_denied() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("webdav-usser-2");
+		Identity reloadedUser = authManager.authenticate(id, id.getName(), JunitTestHelper.PWD);
+		Assert.assertNotNull(reloadedUser);
+		dbInstance.commitAndCloseSession();
+		
+		// login successful
+		Identity authenticatedId = webdavAuthManager.authenticate(null, id.getName(), JunitTestHelper.PWD);
+		Assert.assertNotNull(authenticatedId);
+		
+		// denied login
+		securityManager.saveIdentityStatus(authenticatedId, Identity.STATUS_LOGIN_DENIED, id);
+		dbInstance.commitAndCloseSession();
+		
+		// login failed
+		Identity deniedId = webdavAuthManager.authenticate(null, id.getName(), JunitTestHelper.PWD);
+		Assert.assertNull(deniedId);
+	}
 }
diff --git a/src/test/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerTest.java b/src/test/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerTest.java
index 7864703ae6aa5b89c8f3df9a3b8877a34897a96e..67a109ae1aaf4c7bc9fe55c0030fefdbf87413eb 100644
--- a/src/test/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerTest.java
+++ b/src/test/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerTest.java
@@ -30,15 +30,19 @@ import java.util.concurrent.TimeUnit;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.logging.log4j.Logger;
 import org.junit.Assert;
 import org.junit.Test;
+import org.olat.basesecurity.BaseSecurity;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.DBFactory;
 import org.olat.core.id.Identity;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.Encoder;
+import org.olat.core.util.Encoder.Algorithm;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.UserSession;
+import org.olat.login.auth.OLATAuthManager;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -57,23 +61,104 @@ public class WebDAVManagerTest extends OlatTestCase {
 	@Autowired
 	private DB dbInstance;
 	@Autowired
+	private OLATAuthManager authManager;
+	@Autowired
+	private BaseSecurity securityManager;
+	@Autowired
 	private WebDAVManagerImpl webDAVManager;
 	
 	@Test
 	public void handleBasicAuthentication() {
-		Identity id = JunitTestHelper.createAndPersistIdentityAsUser("dav-user-" + UUID.randomUUID().toString());
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("dav-user-1");
+
+		String credentialsClearText = id.getName() + ":" + JunitTestHelper.PWD;
+		String credentials = StringHelper.encodeBase64(credentialsClearText);
+		HttpServletRequest request = new MockHttpServletRequest();
+		UserSession usess = webDAVManager.handleBasicAuthentication(credentials, request);
+		Assert.assertNotNull(usess);
+		dbInstance.commit();
+	}
+	
+	@Test
+	public void handleBasicAuthentication_denied() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("dav-user-2");
+		authManager.authenticate(id, id.getName(), JunitTestHelper.PWD);
+		dbInstance.commitAndCloseSession();// derived WebDAV authentications saved
 
+		// login successful
 		String credentialsClearText = id.getName() + ":" + JunitTestHelper.PWD;
 		String credentials = StringHelper.encodeBase64(credentialsClearText);
 		HttpServletRequest request = new MockHttpServletRequest();
 		UserSession usess = webDAVManager.handleBasicAuthentication(credentials, request);
 		Assert.assertNotNull(usess);
+		
+		id = securityManager.saveIdentityStatus(id, Identity.STATUS_LOGIN_DENIED, id);
+		dbInstance.commitAndCloseSession();
+		
+		UserSession usessDenied = webDAVManager.handleBasicAuthentication(credentials, request);
+		Assert.assertNull(usessDenied);
+	}
+	
+	@Test
+	public void handleDigestAuthentication() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("dav-user-3");
+		authManager.authenticate(id, id.getName(), JunitTestHelper.PWD);
+		dbInstance.commitAndCloseSession();// derived WebDAV authentications saved
+		
+		HttpServletRequest request = new MockHttpServletRequest();
+		String username = id.getUser().getEmail();
+		String nonce = UUID.randomUUID().toString();
+		String uri = "https://www.openolat.com";
+		String cnonce = UUID.randomUUID().toString();
+		String nc = "nc";
+		String qop = "auth";
+		String token = username + ":" + WebDAVManagerImpl.BASIC_AUTH_REALM + ":" + JunitTestHelper.PWD;
+		String digestedToken = Encoder.encrypt(token, null, Algorithm.md5_iso_8859_1);
+		String ha2 = Encoder.md5hash( ":" + uri);
+		String response = digestedToken + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2;
+		String digestedReponse = Encoder.md5hash(response);
+		
+		DigestAuthentication digested = new DigestAuthentication(username, WebDAVManagerImpl.BASIC_AUTH_REALM, nonce, uri, cnonce, nc, digestedReponse, qop);
+		UserSession usess = webDAVManager.handleDigestAuthentication(digested, request);
+		Assert.assertNotNull(usess);
+		dbInstance.commit();
+	}
+	
+	@Test
+	public void handleDigestAuthentication_denied() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("dav-user-3");
+		authManager.authenticate(id, id.getName(), JunitTestHelper.PWD);
+		dbInstance.commitAndCloseSession();// derived WebDAV authentications saved
+		
+		HttpServletRequest request = new MockHttpServletRequest("POST", "https://www.openolat.col");
+		String username = id.getUser().getEmail();
+		String nonce = UUID.randomUUID().toString();
+		String uri = "https://www.openolat.com";
+		String cnonce = UUID.randomUUID().toString();
+		String nc = "nc";
+		String qop = "auth";
+		String token = username + ":" + WebDAVManagerImpl.BASIC_AUTH_REALM + ":" + JunitTestHelper.PWD;
+		String digestedToken = Encoder.encrypt(token, null, Algorithm.md5_iso_8859_1);
+		String ha2 = Encoder.md5hash("POST:" + uri);
+		String response = digestedToken + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2;
+		String digestedReponse = Encoder.md5hash(response);
+		
+		// login successful
+		DigestAuthentication digested = new DigestAuthentication(username, WebDAVManagerImpl.BASIC_AUTH_REALM, nonce, uri, cnonce, nc, digestedReponse, qop);
+		UserSession usess = webDAVManager.handleDigestAuthentication(digested, request);
+		Assert.assertNotNull(usess);
 		dbInstance.commit();
+		
+		id = securityManager.saveIdentityStatus(id, Identity.STATUS_LOGIN_DENIED, id);
+		dbInstance.commitAndCloseSession();
+		
+		UserSession deniedSession = webDAVManager.handleDigestAuthentication(digested, request);
+		Assert.assertNull(deniedSession);
 	}
 	
 	@Test
 	public void testSetIdentityAsActiv() {
-		Identity id = JunitTestHelper.createAndPersistIdentityAsUser("dav-user-" + UUID.randomUUID().toString());
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("dav-user-4");
 		String credentialsClearText = id.getName() + ":" + JunitTestHelper.PWD;
 		String credentials = StringHelper.encodeBase64(credentialsClearText);
 		
diff --git a/src/test/java/org/olat/restapi/AuthenticationTest.java b/src/test/java/org/olat/restapi/AuthenticationTest.java
index 3c6622a2d126df6ad1ce9a039da8b59b166269a9..21b4d8dd5438ced31d22cf223854f16c05780616 100644
--- a/src/test/java/org/olat/restapi/AuthenticationTest.java
+++ b/src/test/java/org/olat/restapi/AuthenticationTest.java
@@ -49,10 +49,15 @@ import org.apache.http.util.EntityUtils;
 import org.apache.logging.log4j.Logger;
 import org.junit.Assert;
 import org.junit.Test;
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.id.Identity;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
 import org.olat.restapi.security.RestSecurityHelper;
+import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatRestTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -66,6 +71,11 @@ import org.olat.test.OlatRestTestCase;
 public class AuthenticationTest extends OlatRestTestCase {
 	
 	private static final Logger log = Tracing.createLoggerFor(AuthenticationTest.class);
+	
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private BaseSecurity securityManager;
 
 	@Test
 	public void testSessionCookieLogin() throws IOException, URISyntaxException {
@@ -160,6 +170,23 @@ public class AuthenticationTest extends OlatRestTestCase {
 		conn.shutdown();
 	}
 	
+	@Test
+	public void testAuthenticationDenied() throws IOException, URISyntaxException {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("rest-denied");
+		dbInstance.commitAndCloseSession();
+		
+		RestConnection conn = new RestConnection();
+		assertTrue(conn.login(id.getName(), JunitTestHelper.PWD));
+		conn.shutdown();
+		
+		id = securityManager.saveIdentityStatus(id, Identity.STATUS_LOGIN_DENIED, id);
+		dbInstance.commitAndCloseSession();
+		
+		RestConnection conn2 = new RestConnection();
+		Assert.assertFalse(conn2.login(id.getName(), JunitTestHelper.PWD));
+		conn2.shutdown();
+	}
+	
 	@Test
 	public void testBasicAuthentication_concurrent() throws IOException, URISyntaxException {