/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.core.commons.services.webdav.manager; import org.olat.basesecurity.Authentication; import org.olat.basesecurity.BaseSecurity; import org.olat.core.commons.services.webdav.WebDAVModule; import org.olat.core.id.Identity; import org.olat.core.logging.AssertException; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.Encoder; import org.olat.core.util.Encoder.Algorithm; import org.olat.login.LoginModule; import org.olat.login.auth.AuthenticationSPI; import org.olat.login.auth.OLATAuthManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * * Description:<br> * Authentication provider for WebDAV * * <P> * Initial Date: 13 apr. 2010 <br> * @author srosse, stephane.rosse@frentix.com */ @Service("webDAVAuthenticationSpi") public class WebDAVAuthManager implements AuthenticationSPI { public static final String PROVIDER_WEBDAV = "WEBDAV"; public static final String PROVIDER_HA1 = "HA1"; private static final OLog log = Tracing.createLoggerFor(WebDAVAuthManager.class); @Autowired private LoginModule loginModule; @Autowired private WebDAVModule webDAVModule; @Autowired private BaseSecurity securityManager; @Autowired private OLATAuthManager olatAuthenticationSpi; public Identity digestAuthentication(String httpMethod, DigestAuthentication digestAuth) { String username = digestAuth.getUsername(); Authentication olatAuth = securityManager.findAuthenticationByAuthusername(username, WebDAVAuthManager.PROVIDER_HA1); if(olatAuth != null) { if("auth".equals(digestAuth.getQop())) { String nonce = digestAuth.getNonce(); String response = digestAuth.getResponse(); String ha1 = olatAuth.getCredential(); String a2 = httpMethod + ":" + digestAuth.getUri(); String ha2 = Encoder.md5hash(a2); String ver = ha1 + ":" + nonce + ":" + digestAuth.getNc() + ":" + digestAuth.getCnonce() + ":" + digestAuth.getQop() + ":" + ha2; String verity = Encoder.md5hash(ver); if(verity.equals(response)) { Identity identity = olatAuth.getIdentity(); return identity; } else if(log.isDebug()) { // don't log as error, happens all the time with certain clients, e.g. Microsoft-WebDAV-MiniRedir log.debug("Verity::" + verity + " doesn't equals response::" + response); } } } return null; } @Override public Identity authenticate(Identity identity, String login, String password) { Authentication authentication = null; if (identity != null) { authentication = securityManager.findAuthentication(identity, PROVIDER_WEBDAV); } else { authentication = securityManager.findAuthenticationByAuthusername(login, PROVIDER_WEBDAV); } if(authentication == null) { //fallback to standard OLAT authentication return olatAuthenticationSpi.authenticate(identity, login, password); } Identity authenticatedIdentity = authentication.getIdentity(); boolean visible = securityManager.isIdentityVisible(authenticatedIdentity); if (!visible) { return null; } if (securityManager.checkCredentials(authentication, password)) { Algorithm algorithm = Algorithm.find(authentication.getAlgorithm()); if(Algorithm.md5.equals(algorithm)) { authentication = securityManager.updateCredentials(authentication, password, loginModule.getDefaultHashAlgorithm()); } return authentication.getIdentity(); } return null; } @Override public void upgradePassword(Identity identity, String login, String password) { if(webDAVModule.isEnabled() && webDAVModule.isDigestAuthenticationEnabled()) { Authentication digestAuth = securityManager.findAuthentication(identity, PROVIDER_HA1); if(digestAuth == null) { String digestToken = login + ":" + WebDAVManagerImpl.BASIC_AUTH_REALM + ":" + password; Identity reloadedIdentity = securityManager.loadIdentityByKey(identity.getKey()); securityManager.createAndPersistAuthentication(reloadedIdentity, PROVIDER_HA1, login, digestToken, Encoder.Algorithm.md5_noSalt); } } } /** * Change the WEBDAV-Password of an identity * @param doer Identity who is changing the password * @param identity Identity who's password is being changed. * @param newPwd New password. * @return True upon success. */ public boolean changePassword(Identity doer, Identity identity, String newPwd) { if (doer==null) throw new AssertException("password changing identity cannot be undefined!"); if (identity == null || identity.getKey() == null) throw new AssertException("cannot change password on a nonpersisted identity"); //For Basic Authentication auth = securityManager.findAuthentication(identity, PROVIDER_WEBDAV); if (auth == null) { // create new authentication for provider OLAT Identity reloadedIdentity = securityManager.loadIdentityByKey(identity.getKey()); auth = securityManager.createAndPersistAuthentication(reloadedIdentity, PROVIDER_WEBDAV, identity.getName(), newPwd, loginModule.getDefaultHashAlgorithm()); log.audit(doer.getName() + " created new WebDAV authentication for identity: " + identity.getName()); } else { auth = securityManager.updateCredentials(auth, newPwd, loginModule.getDefaultHashAlgorithm()); log.audit(doer.getName() + " set new WebDAV password for identity: " +identity.getName()); } //For Digest changeDigestPassword(doer, identity, identity.getName(), newPwd); return true; } public boolean changeDigestPassword(Identity doer, Identity identity, String username, String newPwd) { if (doer == null) { throw new AssertException("password changing identity cannot be undefined!"); } if (identity == null || identity.getKey() == null) { throw new AssertException("cannot change password on a nonpersisted identity"); } //For Digest if(webDAVModule.isDigestAuthenticationEnabled()) { Authentication authHa1 = securityManager.findAuthentication(identity, PROVIDER_HA1); String digestToken = username + ":" + WebDAVManagerImpl.BASIC_AUTH_REALM + ":" + newPwd; String md5DigestToken = Encoder.encrypt(digestToken, null, Encoder.Algorithm.md5_noSalt); if (authHa1 == null) { // create new authentication for provider OLAT Identity reloadedIdentity = securityManager.loadIdentityByKey(identity.getKey()); authHa1 = securityManager.createAndPersistAuthentication(reloadedIdentity, PROVIDER_HA1, username, digestToken, Encoder.Algorithm.md5_noSalt); log.audit(doer.getName() + " created new WebDAV (HA1) authenticatin for identity: " + identity.getName()); } else if (username != null && (!username.equals(authHa1.getAuthusername()) || !md5DigestToken.equals(authHa1.getCredential()))) { authHa1.setCredential(md5DigestToken); authHa1.setAuthusername(username); authHa1 = securityManager.updateAuthentication(authHa1); log.audit(doer.getName() + " set new WebDAV (HA1) password for identity: " +identity.getName()); } } return true; } }