From 584031f68fde34243805457b4e2b63570ba3df7e Mon Sep 17 00:00:00 2001 From: Brett Porter Date: Thu, 19 Mar 2009 06:10:38 +0000 Subject: [PATCH] clean up the webdav interface to make the code more readable in addition, webdav now honours the delete operation separately to upload improved the HTTP error responses for misconfiguration (500) vs not found on groups git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@755845 13f79535-47bb-0310-9956-ffa450edef68 --- .../security/ArchivaServletAuthenticator.java | 23 +- .../security/ServletAuthenticator.java | 4 +- .../ArchivaServletAuthenticatorTest.java | 141 ++-- .../maven/archiva/web/rss/RssFeedServlet.java | 6 +- .../webdav/ArchivaDavResourceFactory.java | 751 +++++++++--------- .../webdav/ArchivaDavSessionProvider.java | 9 +- .../webdav/ArchivaVirtualDavResource.java | 2 - .../archiva/webdav/util/WebdavMethodUtil.java | 31 +- .../AbstractRepositoryServletTestCase.java | 7 + .../webdav/ArchivaDavSessionProviderTest.java | 5 +- .../webdav/MockServletAuthenticator.java | 2 +- .../RepositoryServletRepositoryGroupTest.java | 2 +- .../webdav/RepositoryServletSecurityTest.java | 124 +-- 13 files changed, 569 insertions(+), 538 deletions(-) diff --git a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaServletAuthenticator.java b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaServletAuthenticator.java index 1b533d30f..40d7a796a 100644 --- a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaServletAuthenticator.java +++ b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaServletAuthenticator.java @@ -62,27 +62,19 @@ public class ArchivaServletAuthenticator } public boolean isAuthorized( HttpServletRequest request, SecuritySession securitySession, String repositoryId, - boolean isWriteRequest ) + String permission ) throws AuthorizationException, UnauthorizedException { // TODO: also check for permission to proxy the resource when MRM-579 is implemented - String permission = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS; - - if ( isWriteRequest ) - { - permission = ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD; - } - AuthorizationResult authzResult = securitySystem.authorize( securitySession, permission, repositoryId ); if ( !authzResult.isAuthorized() ) { if ( authzResult.getException() != null ) { - log.info( "Authorization Denied [ip=" + request.getRemoteAddr() + ",isWriteRequest=" + isWriteRequest + - ",permission=" + permission + ",repo=" + repositoryId + "] : " + - authzResult.getException().getMessage() ); + log.info( "Authorization Denied [ip=" + request.getRemoteAddr() + ",permission=" + permission + + ",repo=" + repositoryId + "] : " + authzResult.getException().getMessage() ); throw new UnauthorizedException( "Access denied for repository " + repositoryId ); } @@ -92,18 +84,11 @@ public class ArchivaServletAuthenticator return true; } - public boolean isAuthorized( String principal, String repoId, boolean isWriteRequest ) + public boolean isAuthorized( String principal, String repoId, String permission ) throws UnauthorizedException { try { - String permission = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS; - - if ( isWriteRequest ) - { - permission = ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD; - } - User user = securitySystem.getUserManager().findUser( principal ); if ( user == null ) { diff --git a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ServletAuthenticator.java b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ServletAuthenticator.java index 5488f139d..ea9cc0d66 100644 --- a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ServletAuthenticator.java +++ b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ServletAuthenticator.java @@ -59,7 +59,7 @@ public interface ServletAuthenticator * @throws UnauthorizedException */ public boolean isAuthorized( HttpServletRequest request, SecuritySession securitySession, String repositoryId, - boolean isWriteRequest ) throws AuthorizationException, UnauthorizedException; + String permission ) throws AuthorizationException, UnauthorizedException; /** * Authorization check specific for user guest, which doesn't go through @@ -74,6 +74,6 @@ public interface ServletAuthenticator * @return * @throws UnauthorizedException */ - public boolean isAuthorized( String principal, String repoId, boolean isWriteRequest ) + public boolean isAuthorized( String principal, String repoId, String permission ) throws UnauthorizedException; } diff --git a/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java b/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java index 19e36929a..89f72848a 100644 --- a/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java +++ b/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java @@ -27,7 +27,7 @@ import org.codehaus.plexus.redback.authorization.UnauthorizedException; import org.codehaus.plexus.redback.system.DefaultSecuritySession; import org.codehaus.plexus.redback.system.SecuritySession; import org.codehaus.plexus.redback.users.User; -import org.codehaus.plexus.redback.users.UserManager; +import org.codehaus.plexus.redback.users.UserManager; import org.easymock.MockControl; @@ -38,48 +38,48 @@ import org.easymock.MockControl; */ public class ArchivaServletAuthenticatorTest extends AbstractSecurityTest -{ +{ private ServletAuthenticator servletAuth; - + private MockControl httpServletRequestControl; - + private HttpServletRequest request; - + @Override public void setUp() throws Exception { super.setUp(); - - servletAuth = ( ServletAuthenticator ) lookup( ServletAuthenticator.class, "default" ); - + + servletAuth = (ServletAuthenticator) lookup( ServletAuthenticator.class, "default" ); + httpServletRequestControl = MockControl.createControl( HttpServletRequest.class ); - request = ( HttpServletRequest ) httpServletRequestControl.getMock(); - + request = (HttpServletRequest) httpServletRequestControl.getMock(); + setupRepository( "corporate" ); } - + @Override protected String getPlexusConfigLocation() { return "org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.xml"; } - + protected void assignRepositoryManagerRole( String principal, String repoId ) throws Exception { roleManager.assignTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_MANAGER, repoId, principal ); } - + public void testIsAuthenticatedUserExists() throws Exception { AuthenticationResult result = new AuthenticationResult( true, "user", null ); boolean isAuthenticated = servletAuth.isAuthenticated( request, result ); - + assertTrue( isAuthenticated ); } - + public void testIsAuthenticatedUserDoesNotExist() throws Exception { @@ -92,132 +92,137 @@ public class ArchivaServletAuthenticatorTest catch ( AuthenticationException e ) { assertEquals( "User Credentials Invalid", e.getMessage() ); - } + } } - + public void testIsAuthorizedUserHasWriteAccess() throws Exception - { + { createUser( USER_ALPACA, "Al 'Archiva' Paca" ); - + assignRepositoryManagerRole( USER_ALPACA, "corporate" ); UserManager userManager = securitySystem.getUserManager(); User user = userManager.findUser( USER_ALPACA ); - + AuthenticationResult result = new AuthenticationResult( true, USER_ALPACA, null ); - + SecuritySession session = new DefaultSecuritySession( result, user ); - boolean isAuthorized = servletAuth.isAuthorized( request, session, "corporate", true ); - + boolean isAuthorized = + servletAuth.isAuthorized( request, session, "corporate", ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ); + assertTrue( isAuthorized ); } - + public void testIsAuthorizedUserHasNoWriteAccess() throws Exception { createUser( USER_ALPACA, "Al 'Archiva' Paca" ); - + assignRepositoryObserverRole( USER_ALPACA, "corporate" ); - + httpServletRequestControl.expectAndReturn( request.getRemoteAddr(), "192.168.111.111" ); - + UserManager userManager = securitySystem.getUserManager(); User user = userManager.findUser( USER_ALPACA ); - + AuthenticationResult result = new AuthenticationResult( true, USER_ALPACA, null ); - + SecuritySession session = new DefaultSecuritySession( result, user ); - + httpServletRequestControl.replay(); - + try { - servletAuth.isAuthorized( request, session, "corporate", true ); - fail( "UnauthorizedException should have been thrown." ); + servletAuth.isAuthorized( request, session, "corporate", ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ); + fail( "UnauthorizedException should have been thrown." ); } catch ( UnauthorizedException e ) { assertEquals( "Access denied for repository corporate", e.getMessage() ); } - + httpServletRequestControl.verify(); } - - + public void testIsAuthorizedUserHasReadAccess() throws Exception - { + { createUser( USER_ALPACA, "Al 'Archiva' Paca" ); - + assignRepositoryObserverRole( USER_ALPACA, "corporate" ); - + UserManager userManager = securitySystem.getUserManager(); User user = userManager.findUser( USER_ALPACA ); - + AuthenticationResult result = new AuthenticationResult( true, USER_ALPACA, null ); - + SecuritySession session = new DefaultSecuritySession( result, user ); - boolean isAuthorized = servletAuth.isAuthorized( request, session, "corporate", false ); - - assertTrue( isAuthorized ); + boolean isAuthorized = + servletAuth.isAuthorized( request, session, "corporate", ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ); + + assertTrue( isAuthorized ); } - + public void testIsAuthorizedUserHasNoReadAccess() throws Exception { createUser( USER_ALPACA, "Al 'Archiva' Paca" ); - + UserManager userManager = securitySystem.getUserManager(); User user = userManager.findUser( USER_ALPACA ); - + AuthenticationResult result = new AuthenticationResult( true, USER_ALPACA, null ); - + SecuritySession session = new DefaultSecuritySession( result, user ); try { - servletAuth.isAuthorized( request, session, "corporate", false ); + servletAuth.isAuthorized( request, session, "corporate", ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ); fail( "UnauthorizedException should have been thrown." ); } catch ( UnauthorizedException e ) { assertEquals( "Access denied for repository corporate", e.getMessage() ); - } + } } - + public void testIsAuthorizedGuestUserHasWriteAccess() throws Exception - { - assignRepositoryManagerRole( USER_GUEST, "corporate" ); - boolean isAuthorized = servletAuth.isAuthorized( USER_GUEST, "corporate", true ); - + { + assignRepositoryManagerRole( USER_GUEST, "corporate" ); + boolean isAuthorized = + servletAuth.isAuthorized( USER_GUEST, "corporate", ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ); + assertTrue( isAuthorized ); } - + public void testIsAuthorizedGuestUserHasNoWriteAccess() throws Exception - { + { assignRepositoryObserverRole( USER_GUEST, "corporate" ); - - boolean isAuthorized = servletAuth.isAuthorized( USER_GUEST, "corporate", true ); + + boolean isAuthorized = + servletAuth.isAuthorized( USER_GUEST, "corporate", ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ); assertFalse( isAuthorized ); } - + public void testIsAuthorizedGuestUserHasReadAccess() throws Exception { assignRepositoryObserverRole( USER_GUEST, "corporate" ); - - boolean isAuthorized = servletAuth.isAuthorized( USER_GUEST, "corporate", false ); - - assertTrue( isAuthorized ); + + boolean isAuthorized = + servletAuth.isAuthorized( USER_GUEST, "corporate", ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ); + + assertTrue( isAuthorized ); } - + public void testIsAuthorizedGuestUserHasNoReadAccess() throws Exception - { - boolean isAuthorized = servletAuth.isAuthorized( USER_GUEST, "corporate", false ); - + { + boolean isAuthorized = + servletAuth.isAuthorized( USER_GUEST, "corporate", ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ); + assertFalse( isAuthorized ); } } diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java index 091489761..1480645b8 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java @@ -38,6 +38,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; import org.apache.maven.archiva.database.ArchivaDatabaseException; import org.apache.maven.archiva.security.AccessDeniedException; +import org.apache.maven.archiva.security.ArchivaRoleConstants; import org.apache.maven.archiva.security.ArchivaSecurityException; import org.apache.maven.archiva.security.PrincipalNotFoundException; import org.apache.maven.archiva.security.ServletAuthenticator; @@ -293,8 +294,9 @@ public class RssFeedServlet AuthenticationResult result = httpAuth.getAuthenticationResult( req, null ); SecuritySession securitySession = httpAuth.getSecuritySession( req.getSession( true ) ); - if ( servletAuth.isAuthenticated( req, result ) && - servletAuth.isAuthorized( req, securitySession, repoId, false ) ) + if ( servletAuth.isAuthenticated( req, result ) + && servletAuth.isAuthorized( req, securitySession, repoId, + ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ) ) { return true; } diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java index 54fb20e50..96effbba6 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java @@ -91,7 +91,7 @@ import org.slf4j.LoggerFactory; */ public class ArchivaDavResourceFactory implements DavResourceFactory, Auditable -{ +{ private static final String PROXIED_SUFFIX = " (proxied)"; private static final String HTTP_PUT_METHOD = "PUT"; @@ -148,16 +148,16 @@ public class ArchivaDavResourceFactory */ private final LockManager lockManager = new SimpleLockManager(); - /** - * @plexus.requirement + /** + * @plexus.requirement */ private RepositoryContentConsumers consumers; - + /** * @plexus.requirement */ private ChecksumFile checksum; - + /** * @plexus.requirement role-hint="sha1" */ @@ -167,342 +167,355 @@ public class ArchivaDavResourceFactory * @plexus.requirement role-hint="md5"; */ private Digester digestMd5; - + public DavResource createResource( final DavResourceLocator locator, final DavServletRequest request, final DavServletResponse response ) throws DavException { - checkLocatorIsInstanceOfRepositoryLocator( locator ); - ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator; - + ArchivaDavResourceLocator archivaLocator = checkLocatorIsInstanceOfRepositoryLocator( locator ); + RepositoryGroupConfiguration repoGroupConfig = archivaConfiguration.getConfiguration().getRepositoryGroupsAsMap().get( archivaLocator.getRepositoryId() ); - List repositories = new ArrayList(); - boolean isGet = WebdavMethodUtil.isReadMethod( request.getMethod() ); - boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); - + String activePrincipal = getActivePrincipal( request ); + + List resourcesInAbsolutePath = new ArrayList(); + + boolean readMethod = WebdavMethodUtil.isReadMethod( request.getMethod() ); + DavResource resource; if ( repoGroupConfig != null ) { - if( WebdavMethodUtil.isWriteMethod( request.getMethod() ) ) + if ( !readMethod ) { throw new DavException( HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Write method not allowed for repository groups." ); } - repositories.addAll( repoGroupConfig.getRepositories() ); // handle browse requests for virtual repos if ( RepositoryPathUtil.getLogicalResource( archivaLocator.getOrigResourcePath() ).endsWith( "/" ) ) { - return getResource( request, repositories, archivaLocator ); + return getResource( request, repoGroupConfig.getRepositories(), archivaLocator ); + } + else + { + resource = + processRepositoryGroup( locator, request, archivaLocator, repoGroupConfig.getRepositories(), + activePrincipal, readMethod, resourcesInAbsolutePath ); } } else - { - repositories.add( archivaLocator.getRepositoryId() ); - } - - //MRM-419 - Windows Webdav support. Should not 404 if there is no content. - if (StringUtils.isEmpty(archivaLocator.getRepositoryId())) - { - throw new DavException(HttpServletResponse.SC_NO_CONTENT); - } - - List availableResources = new ArrayList(); - List resourcesInAbsolutePath = new ArrayList(); - DavException e = null; - - for ( String repositoryId : repositories ) { ManagedRepositoryContent managedRepository = null; try { - managedRepository = getManagedRepository( repositoryId ); + managedRepository = repositoryFactory.getManagedRepositoryContent( archivaLocator.getRepositoryId() ); } - catch ( DavException de ) + catch ( RepositoryNotFoundException e ) { - throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid managed repository <" + - repositoryId + ">" ); + throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid repository: " + + archivaLocator.getRepositoryId() ); + } + catch ( RepositoryException e ) + { + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e ); } - - DavResource resource = null; - - if ( !locator.getResourcePath().startsWith( ArchivaDavResource.HIDDEN_PATH_PREFIX ) ) - { - if ( managedRepository != null ) - { - try - { - if( isAuthorized( request, repositoryId ) ) - { - LogicalResource logicalResource = - new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) ); - - if ( isGet ) - { - resource = doGet( managedRepository, request, archivaLocator, logicalResource ); - } - - if ( isPut ) - { - resource = doPut( managedRepository, request, archivaLocator, logicalResource ); - } - } - } - catch ( DavException de ) - { - e = de; - continue; - } - if( resource == null ) - { - e = new DavException( HttpServletResponse.SC_NOT_FOUND, "Resource does not exist" ); - } - else - { - availableResources.add( resource ); + resource = + processRepository( locator, request, archivaLocator, readMethod, activePrincipal, + archivaLocator.getRepositoryId(), managedRepository ); - String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ); - resourcesInAbsolutePath.add( managedRepository.getRepoRoot() + logicalResource ); - } - } - else - { - e = new DavException( HttpServletResponse.SC_NOT_FOUND, "Repository does not exist" ); - } - } - } - - if ( availableResources.isEmpty() ) - { - throw e; + String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ); + resourcesInAbsolutePath.add( managedRepository.getRepoRoot() + logicalResource ); } - + String requestedResource = request.getRequestURI(); - + // MRM-872 : merge all available metadata - // merge metadata only when requested via the repo group - if ( ( repositoryRequest.isMetadata( requestedResource ) || ( requestedResource.endsWith( "metadata.xml.sha1" ) || requestedResource.endsWith( "metadata.xml.md5" ) ) ) && - repoGroupConfig != null ) - { + // merge metadata only when requested via the repo group + if ( ( repositoryRequest.isMetadata( requestedResource ) || ( requestedResource.endsWith( "metadata.xml.sha1" ) || requestedResource.endsWith( "metadata.xml.md5" ) ) ) + && repoGroupConfig != null ) + { // this should only be at the project level not version level! - if( isProjectReference( requestedResource ) ) + if ( isProjectReference( requestedResource ) ) { String artifactId = StringUtils.substringBeforeLast( requestedResource.replace( '\\', '/' ), "/" ); artifactId = StringUtils.substringAfterLast( artifactId, "/" ); - - ArchivaDavResource res = ( ArchivaDavResource ) availableResources.get( 0 ); - String filePath = StringUtils.substringBeforeLast( res.getLocalResource().getAbsolutePath().replace( '\\', '/' ), "/" ); + + ArchivaDavResource res = (ArchivaDavResource) resource; + String filePath = + StringUtils.substringBeforeLast( res.getLocalResource().getAbsolutePath().replace( '\\', '/' ), "/" ); filePath = filePath + "/maven-metadata-" + repoGroupConfig.getId() + ".xml"; - - // for MRM-872 handle checksums of the merged metadata files - if( repositoryRequest.isSupportFile( requestedResource ) ) + + // for MRM-872 handle checksums of the merged metadata files + if ( repositoryRequest.isSupportFile( requestedResource ) ) { - File metadataChecksum = new File( filePath + "." - + StringUtils.substringAfterLast( requestedResource, "." ) ); - if( metadataChecksum.exists() ) + File metadataChecksum = + new File( filePath + "." + StringUtils.substringAfterLast( requestedResource, "." ) ); + if ( metadataChecksum.exists() ) { LogicalResource logicalResource = new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) ); - - String activePrincipal = getActivePrincipal( request ); - ArchivaDavResource metadataChecksumResource = + resource = new ArchivaDavResource( metadataChecksum.getAbsolutePath(), logicalResource.getPath(), null, request.getRemoteAddr(), activePrincipal, request.getDavSession(), archivaLocator, this, mimeTypes, auditListeners, consumers ); - availableResources.add( 0, metadataChecksumResource ); } } else - { // merge the metadata of all repos under group - ArchivaRepositoryMetadata mergedMetadata = new ArchivaRepositoryMetadata(); - for ( String resourceAbsPath : resourcesInAbsolutePath ) - { + { + if ( resourcesInAbsolutePath != null && resourcesInAbsolutePath.size() > 1 ) + { + // merge the metadata of all repos under group + ArchivaRepositoryMetadata mergedMetadata = new ArchivaRepositoryMetadata(); + for ( String resourceAbsPath : resourcesInAbsolutePath ) + { + try + { + File metadataFile = new File( resourceAbsPath ); + ArchivaRepositoryMetadata repoMetadata = RepositoryMetadataReader.read( metadataFile ); + mergedMetadata = RepositoryMetadataMerge.merge( mergedMetadata, repoMetadata ); + } + catch ( RepositoryMetadataException r ) + { + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Error occurred while reading metadata file." ); + } + } + try - { - File metadataFile = new File( resourceAbsPath ); - ArchivaRepositoryMetadata repoMetadata = RepositoryMetadataReader.read( metadataFile ); - mergedMetadata = RepositoryMetadataMerge.merge( mergedMetadata, repoMetadata ); + { + File resourceFile = writeMergedMetadataToFile( mergedMetadata, filePath ); + + LogicalResource logicalResource = + new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) ); + + resource = + new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), + null, request.getRemoteAddr(), activePrincipal, + request.getDavSession(), archivaLocator, this, mimeTypes, + auditListeners, consumers ); } catch ( RepositoryMetadataException r ) { throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Error occurred while reading metadata file." ); - } - } - - try - { - File resourceFile = writeMergedMetadataToFile( mergedMetadata, filePath ); - - LogicalResource logicalResource = - new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) ); - - String activePrincipal = getActivePrincipal( request ); - - ArchivaDavResource metadataResource = - new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), null, - request.getRemoteAddr(), activePrincipal, request.getDavSession(), - archivaLocator, this, mimeTypes, auditListeners, consumers ); - availableResources.add( 0, metadataResource ); - } - catch ( RepositoryMetadataException r ) - { - throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Error occurred while writing metadata file." ); - } - catch ( IOException ie ) - { - throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Error occurred while generating checksum files." ); - } - catch ( DigesterException de ) - { - throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Error occurred while generating checksum files." ); + "Error occurred while writing metadata file." ); + } + catch ( IOException ie ) + { + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Error occurred while generating checksum files." ); + } + catch ( DigesterException de ) + { + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Error occurred while generating checksum files." ); + } } } } } - - DavResource resource = availableResources.get( 0 ); - setHeaders(response, locator, resource ); + + setHeaders( response, locator, resource ); // compatibility with MRM-440 to ensure browsing the repository works ok - if ( resource.isCollection() && !request.getRequestURI().endsWith("/" ) ) + if ( resource.isCollection() && !request.getRequestURI().endsWith( "/" ) ) { throw new BrowserRedirectException( resource.getHref() ); } - resource.addLockManager(lockManager); + resource.addLockManager( lockManager ); return resource; } - public DavResource createResource( final DavResourceLocator locator, final DavSession davSession ) + private DavResource processRepositoryGroup( final DavResourceLocator locator, final DavServletRequest request, + ArchivaDavResourceLocator archivaLocator, List repositories, + String activePrincipal, boolean readMethod, + List resourcesInAbsolutePath ) throws DavException { - checkLocatorIsInstanceOfRepositoryLocator( locator ); - ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator; - DavResource resource = null; - if ( !locator.getResourcePath().startsWith( ArchivaDavResource.HIDDEN_PATH_PREFIX ) ) + DavException storedException = null; + + for ( String repositoryId : repositories ) { - ManagedRepositoryContent managedRepository = getManagedRepository( archivaLocator.getRepositoryId() ); - String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ); - File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource ); - resource = - new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource, - managedRepository.getRepository(), davSession, archivaLocator, this, mimeTypes, - auditListeners, consumers ); + ManagedRepositoryContent managedRepository = null; + + try + { + managedRepository = repositoryFactory.getManagedRepositoryContent( repositoryId ); + } + catch ( RepositoryNotFoundException e ) + { + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e ); + } + catch ( RepositoryException e ) + { + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e ); + } + + try + { + DavResource resource1 = + processRepository( locator, request, archivaLocator, readMethod, activePrincipal, repositoryId, + managedRepository ); + if ( resource == null ) + { + resource = resource1; + } + + String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ); + resourcesInAbsolutePath.add( managedRepository.getRepoRoot() + logicalResource ); + } + catch ( DavException e ) + { + storedException = e; + } } - resource.addLockManager(lockManager); - return resource; - } - private DavResource doGet( ManagedRepositoryContent managedRepository, DavServletRequest request, - ArchivaDavResourceLocator locator, LogicalResource logicalResource ) - throws DavException - { - File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() ); - - //MRM-893, dont send back a file when user intentionally wants a directory - if ( locator.getHref( false ).endsWith( "/" ) ) + if ( resource == null ) { - if ( ! resourceFile.isDirectory() ) + if ( storedException != null ) + { + throw storedException; + } + else { - //force a resource not found - return null; + throw new DavException( HttpServletResponse.SC_NOT_FOUND ); } } + return resource; + } - String activePrincipal = getActivePrincipal( request ); - - ArchivaDavResource resource = - new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), - managedRepository.getRepository(), request.getRemoteAddr(), activePrincipal, - request.getDavSession(), locator, this, mimeTypes, auditListeners, consumers ); - - if ( !resource.isCollection() ) + private DavResource processRepository( final DavResourceLocator locator, final DavServletRequest request, + ArchivaDavResourceLocator archivaLocator, boolean readMethod, + String activePrincipal, String repositoryId, + ManagedRepositoryContent managedRepository ) + throws DavException + { + DavResource resource = null; + if ( isAuthorized( request, repositoryId ) ) { - boolean previouslyExisted = resourceFile.exists(); + LogicalResource logicalResource = + new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) ); - // At this point the incoming request can either be in default or - // legacy layout format. - boolean fromProxy = fetchContentFromProxies( managedRepository, request, logicalResource ); + File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() ); + resource = + new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), + managedRepository.getRepository(), request.getRemoteAddr(), activePrincipal, + request.getDavSession(), archivaLocator, this, mimeTypes, auditListeners, + consumers ); - try + if ( readMethod ) { - // Perform an adjustment of the resource to the managed - // repository expected path. - String localResourcePath = - repositoryRequest.toNativePath( logicalResource.getPath(), managedRepository ); - resourceFile = new File( managedRepository.getRepoRoot(), localResourcePath ); - } - catch ( LayoutException e ) - { - if ( previouslyExisted ) + if ( archivaLocator.getHref( false ).endsWith( "/" ) && !resourceFile.isDirectory() ) { - return resource; + // force a resource not found + throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Resource does not exist" ); } - throw new DavException( HttpServletResponse.SC_NOT_FOUND, e ); - } + else + { + if ( !resource.isCollection() ) + { + boolean previouslyExisted = resourceFile.exists(); - // Attempt to fetch the resource from any defined proxy. - if ( fromProxy ) - { - String repositoryId = locator.getRepositoryId(); - String event = ( previouslyExisted ? AuditEvent.MODIFY_FILE : AuditEvent.CREATE_FILE ) + PROXIED_SUFFIX; - triggerAuditEvent( request.getRemoteAddr(), repositoryId, logicalResource.getPath(), event, - activePrincipal ); - } + // Attempt to fetch the resource from any defined proxy. + boolean fromProxy = fetchContentFromProxies( managedRepository, request, logicalResource ); - if ( !resourceFile.exists() ) - { - resource = null; + // At this point the incoming request can either be in default or + // legacy layout format. + try + { + // Perform an adjustment of the resource to the managed + // repository expected path. + String localResourcePath = + repositoryRequest.toNativePath( logicalResource.getPath(), managedRepository ); + resourceFile = new File( managedRepository.getRepoRoot(), localResourcePath ); + resource = + new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), + managedRepository.getRepository(), request.getRemoteAddr(), + activePrincipal, request.getDavSession(), archivaLocator, this, + mimeTypes, auditListeners, consumers ); + } + catch ( LayoutException e1 ) + { + if ( !resourceFile.exists() ) + { + throw new DavException( HttpServletResponse.SC_NOT_FOUND, e1 ); + } + } + + if ( fromProxy ) + { + String repositoryId1 = archivaLocator.getRepositoryId(); + String event = + ( previouslyExisted ? AuditEvent.MODIFY_FILE : AuditEvent.CREATE_FILE ) + + PROXIED_SUFFIX; + triggerAuditEvent( request.getRemoteAddr(), repositoryId1, logicalResource.getPath(), + event, activePrincipal ); + } + + if ( !resourceFile.exists() ) + { + throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Resource does not exist" ); + } + } + } } - else + + if ( request.getMethod().equals( HTTP_PUT_METHOD ) ) { - resource = - new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), - managedRepository.getRepository(), request.getRemoteAddr(), - activePrincipal, request.getDavSession(), locator, this, mimeTypes, - auditListeners, consumers ); + /* + * Create parent directories that don't exist when writing a file This actually makes this + * implementation not compliant to the WebDAV RFC - but we have enough knowledge about how the + * collection is being used to do this reasonably and some versions of Maven's WebDAV don't correctly + * create the collections themselves. + */ + + File rootDirectory = new File( managedRepository.getRepoRoot() ); + File destDir = new File( rootDirectory, logicalResource.getPath() ).getParentFile(); + + if ( !destDir.exists() ) + { + destDir.mkdirs(); + String relPath = PathUtil.getRelative( rootDirectory.getAbsolutePath(), destDir ); + triggerAuditEvent( request.getRemoteAddr(), logicalResource.getPath(), relPath, + AuditEvent.CREATE_DIR, activePrincipal ); + } } } return resource; } - private DavResource doPut( ManagedRepositoryContent managedRepository, DavServletRequest request, - ArchivaDavResourceLocator locator, LogicalResource logicalResource ) + public DavResource createResource( final DavResourceLocator locator, final DavSession davSession ) throws DavException { - /* - * Create parent directories that don't exist when writing a file This actually makes this implementation not - * compliant to the WebDAV RFC - but we have enough knowledge about how the collection is being used to do this - * reasonably and some versions of Maven's WebDAV don't correctly create the collections themselves. - */ - - File rootDirectory = new File( managedRepository.getRepoRoot() ); - File destDir = new File( rootDirectory, logicalResource.getPath() ).getParentFile(); - - String activePrincipal = getActivePrincipal( request ); + ArchivaDavResourceLocator archivaLocator = checkLocatorIsInstanceOfRepositoryLocator( locator ); - if ( request.getMethod().equals(HTTP_PUT_METHOD) && !destDir.exists() ) + ManagedRepositoryContent managedRepository; + try { - destDir.mkdirs(); - String relPath = PathUtil.getRelative( rootDirectory.getAbsolutePath(), destDir ); - triggerAuditEvent( request.getRemoteAddr(), logicalResource.getPath(), relPath, AuditEvent.CREATE_DIR, - activePrincipal ); + managedRepository = repositoryFactory.getManagedRepositoryContent( archivaLocator.getRepositoryId() ); } - - File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() ); - - return new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), - managedRepository.getRepository(), request.getRemoteAddr(), activePrincipal, - request.getDavSession(), locator, this, mimeTypes, auditListeners, consumers ); + catch ( RepositoryNotFoundException e ) + { + throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid repository: " + + archivaLocator.getRepositoryId() ); + } + catch ( RepositoryException e ) + { + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e ); + } + + String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ); + File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource ); + DavResource resource = + new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource, managedRepository.getRepository(), + davSession, archivaLocator, this, mimeTypes, auditListeners, consumers ); + + resource.addLockManager( lockManager ); + return resource; } private boolean fetchContentFromProxies( ManagedRepositoryContent managedRepository, DavServletRequest request, @@ -519,7 +532,7 @@ public class ArchivaDavResourceFactory // Is it a Metadata resource? if ( repositoryRequest.isDefault( resource.getPath() ) && repositoryRequest.isMetadata( resource.getPath() ) ) { - return connectors.fetchMetatadaFromProxies(managedRepository, resource.getPath()) != null; + return connectors.fetchMetatadaFromProxies( managedRepository, resource.getPath() ) != null; } // Not any of the above? Then it's gotta be an artifact reference. @@ -596,7 +609,7 @@ public class ArchivaDavResourceFactory } finally { - if (reader != null) + if ( reader != null ) { reader.close(); } @@ -676,44 +689,38 @@ public class ArchivaDavResourceFactory response.addHeader( "Cache-Control", "no-cache" ); } - //We need to specify this so connecting wagons can work correctly - response.addDateHeader("last-modified", resource.getModificationTime()); + // We need to specify this so connecting wagons can work correctly + response.addDateHeader( "last-modified", resource.getModificationTime() ); // TODO: [MRM-524] determine http caching options for other types of files (artifacts, sha1, md5, snapshots) } - private ManagedRepositoryContent getManagedRepository( String respositoryId ) + private ArchivaDavResourceLocator checkLocatorIsInstanceOfRepositoryLocator( DavResourceLocator locator ) throws DavException { - if ( respositoryId != null ) + if ( !( locator instanceof ArchivaDavResourceLocator ) ) { - try - { - return repositoryFactory.getManagedRepositoryContent( respositoryId ); - } - catch ( RepositoryNotFoundException e ) - { - throw new DavException( HttpServletResponse.SC_NOT_FOUND, e ); - } - catch ( RepositoryException e ) - { - throw new DavException( HttpServletResponse.SC_NOT_FOUND, e ); - } + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Locator does not implement RepositoryLocator" ); } - return null; - } - private void checkLocatorIsInstanceOfRepositoryLocator( DavResourceLocator locator ) - throws DavException - { - if ( !( locator instanceof RepositoryLocator ) ) + // Hidden paths + if ( locator.getResourcePath().startsWith( ArchivaDavResource.HIDDEN_PATH_PREFIX ) ) { - throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Locator does not implement RepositoryLocator" ); + throw new DavException( HttpServletResponse.SC_NOT_FOUND ); + } + + ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator; + + // MRM-419 - Windows Webdav support. Should not 404 if there is no content. + if ( StringUtils.isEmpty( archivaLocator.getRepositoryId() ) ) + { + throw new DavException( HttpServletResponse.SC_NO_CONTENT ); } + return archivaLocator; } - class LogicalResource + private static class LogicalResource { private String path; @@ -735,36 +742,36 @@ public class ArchivaDavResourceFactory protected boolean isAuthorized( DavServletRequest request, String repositoryId ) throws DavException - { + { try - { + { AuthenticationResult result = httpAuth.getAuthenticationResult( request, null ); SecuritySession securitySession = httpAuth.getSecuritySession( request.getSession( true ) ); - return servletAuth.isAuthenticated( request, result ) && - servletAuth.isAuthorized( request, securitySession, repositoryId, - WebdavMethodUtil.isWriteMethod( request.getMethod() ) ); + return servletAuth.isAuthenticated( request, result ) + && servletAuth.isAuthorized( request, securitySession, repositoryId, + WebdavMethodUtil.getMethodPermission( request.getMethod() ) ); } catch ( AuthenticationException e ) - { - boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); - - // safety check for MRM-911 + { + // safety check for MRM-911 String guest = UserManager.GUEST_USERNAME; try { - if( servletAuth.isAuthorized( guest, - ( ( ArchivaDavResourceLocator ) request.getRequestLocator() ).getRepositoryId(), isPut ) ) - { + if ( servletAuth.isAuthorized( + guest, + ( (ArchivaDavResourceLocator) request.getRequestLocator() ).getRepositoryId(), + WebdavMethodUtil.getMethodPermission( request.getMethod() ) ) ) + { return true; } } catch ( UnauthorizedException ae ) { throw new UnauthorizedDavException( repositoryId, - "You are not authenticated and authorized to access any repository." ); + "You are not authenticated and authorized to access any repository." ); } - + throw new UnauthorizedDavException( repositoryId, "You are not authenticated" ); } catch ( MustChangePasswordException e ) @@ -786,7 +793,8 @@ public class ArchivaDavResourceFactory } } - private DavResource getResource( DavServletRequest request, List repositories, ArchivaDavResourceLocator locator ) + private DavResource getResource( DavServletRequest request, List repositories, + ArchivaDavResourceLocator locator ) throws DavException { List mergedRepositoryContents = new ArrayList(); @@ -799,43 +807,67 @@ public class ArchivaDavResourceFactory // otherwise, prompt for authentication. String activePrincipal = getActivePrincipal( request ); - + boolean allow = isAllowedToContinue( request, repositories, activePrincipal ); - if( allow ) + if ( allow ) { - boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); - - for( String repository : repositories ) + for ( String repository : repositories ) { - // for prompted authentication - if( httpAuth.getSecuritySession( request.getSession( true ) ) != null ) + ManagedRepositoryContent managedRepository = null; + + try { - try - { - if( isAuthorized( request, repository ) ) - { - getResource( locator, mergedRepositoryContents, logicalResource, repository ); - } - } - catch ( DavException e ) - { - continue; - } + managedRepository = repositoryFactory.getManagedRepositoryContent( repository ); } - else + catch ( RepositoryNotFoundException e ) + { + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Invalid managed repository <" + repository + ">: " + e.getMessage() ); + } + catch ( RepositoryException e ) + { + throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Invalid managed repository <" + repository + ">: " + e.getMessage() ); + } + + File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() ); + if ( resourceFile.exists() ) { - // for the current user logged in - try + // for prompted authentication + if ( httpAuth.getSecuritySession( request.getSession( true ) ) != null ) { - if( servletAuth.isAuthorized( activePrincipal, repository, isPut ) ) + try + { + if ( isAuthorized( request, repository ) ) + { + mergedRepositoryContents.add( resourceFile ); + } + } + catch ( DavException e ) { - getResource( locator, mergedRepositoryContents, logicalResource, repository ); + // TODO: review exception handling + log.debug( "Skipping repository '" + managedRepository + "' for user '" + activePrincipal + + "': " + e.getMessage() ); } } - catch ( UnauthorizedException e ) + else { - continue; + // for the current user logged in + try + { + if ( servletAuth.isAuthorized( activePrincipal, repository, + WebdavMethodUtil.getMethodPermission( request.getMethod() ) ) ) + { + mergedRepositoryContents.add( resourceFile ); + } + } + catch ( UnauthorizedException e ) + { + // TODO: review exception handling + log.debug( "Skipping repository '" + managedRepository + "' for user '" + activePrincipal + + "': " + e.getMessage() ); + } } } } @@ -846,10 +878,11 @@ public class ArchivaDavResourceFactory } ArchivaVirtualDavResource resource = - new ArchivaVirtualDavResource( mergedRepositoryContents, logicalResource.getPath(), mimeTypes, locator, this ); + new ArchivaVirtualDavResource( mergedRepositoryContents, logicalResource.getPath(), mimeTypes, locator, + this ); // compatibility with MRM-440 to ensure browsing the repository group works ok - if ( resource.isCollection() && !request.getRequestURI().endsWith("/" ) ) + if ( resource.isCollection() && !request.getRequestURI().endsWith( "/" ) ) { throw new BrowserRedirectException( resource.getHref() ); } @@ -863,38 +896,9 @@ public class ArchivaDavResourceFactory return sessionUser != null ? sessionUser.getUsername() : UserManager.GUEST_USERNAME; } - private void getResource( ArchivaDavResourceLocator locator, List mergedRepositoryContents, - LogicalResource logicalResource, String repository ) - throws DavException - { - ManagedRepositoryContent managedRepository = null; - - try - { - managedRepository = getManagedRepository( repository ); - } - catch ( DavException de ) - { - throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid managed repository <" + - repository + ">" ); - } - - if ( !locator.getResourcePath().startsWith( ArchivaVirtualDavResource.HIDDEN_PATH_PREFIX ) ) - { - if( managedRepository != null ) - { - File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() ); - if( resourceFile.exists() ) - { - mergedRepositoryContents.add( resourceFile ); - } - } - } - } - /** * Check if the current user is authorized to access any of the repos - * + * * @param request * @param repositories * @param activePrincipal @@ -904,21 +908,20 @@ public class ArchivaDavResourceFactory { boolean allow = false; - // if securitySession != null, it means that the user was prompted for authentication - if( httpAuth.getSecuritySession( request.getSession() ) != null ) + if ( httpAuth.getSecuritySession( request.getSession() ) != null ) { - for( String repository : repositories ) + for ( String repository : repositories ) { try { - if( isAuthorized( request, repository ) ) + if ( isAuthorized( request, repository ) ) { allow = true; break; } } - catch( DavException e ) + catch ( DavException e ) { continue; } @@ -926,12 +929,12 @@ public class ArchivaDavResourceFactory } else { - boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); - for( String repository : repositories ) + for ( String repository : repositories ) { try - { - if( servletAuth.isAuthorized( activePrincipal, repository, isPut ) ) + { + if ( servletAuth.isAuthorized( activePrincipal, repository, + WebdavMethodUtil.getMethodPermission( request.getMethod() ) ) ) { allow = true; break; @@ -949,55 +952,55 @@ public class ArchivaDavResourceFactory private File writeMergedMetadataToFile( ArchivaRepositoryMetadata mergedMetadata, String outputFilename ) throws RepositoryMetadataException, DigesterException, IOException - { - File outputFile = new File( outputFilename ); - if( outputFile.exists() ) + { + File outputFile = new File( outputFilename ); + if ( outputFile.exists() ) { FileUtils.deleteQuietly( outputFile ); } - + outputFile.getParentFile().mkdirs(); RepositoryMetadataWriter.write( mergedMetadata, outputFile ); - + createChecksumFile( outputFilename, digestSha1 ); createChecksumFile( outputFilename, digestMd5 ); - + return outputFile; } - + private void createChecksumFile( String path, Digester digester ) throws DigesterException, IOException - { - File checksumFile = new File( path + digester.getFilenameExtension() ); + { + File checksumFile = new File( path + digester.getFilenameExtension() ); if ( !checksumFile.exists() ) { FileUtils.deleteQuietly( checksumFile ); - checksum.createChecksum( new File( path ), digester ); + checksum.createChecksum( new File( path ), digester ); } else if ( !checksumFile.isFile() ) { log.error( "Checksum file is not a file." ); } } - + private boolean isProjectReference( String requestedResource ) - { - try - { - metadataTools.toVersionedReference( requestedResource ); - return false; - } - catch ( RepositoryMetadataException re ) - { - return true; - } + { + try + { + metadataTools.toVersionedReference( requestedResource ); + return false; + } + catch ( RepositoryMetadataException re ) + { + return true; + } } - + public void setServletAuth( ServletAuthenticator servletAuth ) { this.servletAuth = servletAuth; } - + public void setHttpAuth( HttpAuthenticator httpAuth ) { this.httpAuth = httpAuth; diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProvider.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProvider.java index 6157f1cb8..a5c447e8d 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProvider.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProvider.java @@ -66,16 +66,15 @@ public class ArchivaDavSessionProvider } catch ( AuthenticationException e ) { - boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); - // safety check for MRM-911 String guest = UserManager.GUEST_USERNAME; try { - if( servletAuth.isAuthorized( guest, - ( ( ArchivaDavResourceLocator ) request.getRequestLocator() ).getRepositoryId(), isPut ) ) + if ( servletAuth.isAuthorized( guest, + ( (ArchivaDavResourceLocator) request.getRequestLocator() ).getRepositoryId(), + WebdavMethodUtil.getMethodPermission( request.getMethod() ) ) ) { - request.setDavSession(new ArchivaDavSession()); + request.setDavSession( new ArchivaDavSession() ); return true; } } diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java index 4bb3a140a..47bd88d15 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java @@ -59,8 +59,6 @@ import org.joda.time.format.ISODateTimeFormat; public class ArchivaVirtualDavResource implements DavResource { - public static final String HIDDEN_PATH_PREFIX = "."; - private static final String COMPLIANCE_CLASS = "1"; private ArchivaDavResourceLocator locator; diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/WebdavMethodUtil.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/WebdavMethodUtil.java index 9d488f7b6..fad10e294 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/WebdavMethodUtil.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/WebdavMethodUtil.java @@ -20,13 +20,15 @@ package org.apache.maven.archiva.webdav.util; */ import org.apache.commons.lang.StringUtils; +import org.apache.maven.archiva.security.ArchivaRoleConstants; import java.util.ArrayList; import java.util.List; +import java.util.Locale; /** - * WebdavMethodUtil - * + * WebdavMethodUtil + * * @version $Id: WebdavMethodUtil.java 5412 2007-01-13 01:18:47Z joakime $ */ public class WebdavMethodUtil @@ -43,23 +45,32 @@ public class WebdavMethodUtil READ_METHODS.add( "REPORT" ); } - public static boolean isReadMethod( String method ) + public static String getMethodPermission( String method ) { if ( StringUtils.isBlank( method ) ) { - return false; + throw new IllegalArgumentException( "WebDAV method is empty" ); + } + if ( READ_METHODS.contains( method.toUpperCase( Locale.US ) ) ) + { + return ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS; + } + else if ( "DELETE".equals( method.toUpperCase( Locale.US ) ) ) + { + return ArchivaRoleConstants.OPERATION_REPOSITORY_DELETE; + } + else + { + return ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD; } - - return READ_METHODS.contains( method.toUpperCase() ); } - public static boolean isWriteMethod( String method ) + public static boolean isReadMethod( String method ) { if ( StringUtils.isBlank( method ) ) { - return false; + throw new IllegalArgumentException( "WebDAV method is empty" ); } - - return !READ_METHODS.contains( method.toUpperCase() ); + return READ_METHODS.contains( method.toUpperCase( Locale.US ) ); } } diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/AbstractRepositoryServletTestCase.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/AbstractRepositoryServletTestCase.java index 7f7b724b8..fe1a6be63 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/AbstractRepositoryServletTestCase.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/AbstractRepositoryServletTestCase.java @@ -97,6 +97,13 @@ public abstract class AbstractRepositoryServletTestCase .getResponseCode() ); } + protected void assertResponseInternalServerError( WebResponse response ) + { + assertNotNull( "Should have recieved a response", response ); + Assert.assertEquals( "Should have been an 500/Internal Server Error response code.", HttpServletResponse.SC_INTERNAL_SERVER_ERROR, response + .getResponseCode() ); + } + protected ManagedRepositoryConfiguration createManagedRepository( String id, String name, File location ) { ManagedRepositoryConfiguration repo = new ManagedRepositoryConfiguration(); diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProviderTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProviderTest.java index 370b30ff6..c03e36ff2 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProviderTest.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProviderTest.java @@ -360,13 +360,14 @@ public class ArchivaDavSessionProviderTest extends TestCase return true; } - public boolean isAuthorized(HttpServletRequest arg0, SecuritySession arg1, String arg2, boolean arg3) + public boolean isAuthorized( HttpServletRequest request, SecuritySession securitySession, String repositoryId, + String permission ) throws AuthorizationException, UnauthorizedException { return true; } - public boolean isAuthorized(String arg0, String arg1, boolean isWriteRequest) + public boolean isAuthorized( String principal, String repoId, String permission ) throws UnauthorizedException { return true; diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/MockServletAuthenticator.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/MockServletAuthenticator.java index 4ea71a929..0f1b8ab6a 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/MockServletAuthenticator.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/MockServletAuthenticator.java @@ -26,7 +26,7 @@ public class MockServletAuthenticator extends ArchivaServletAuthenticator { @Override - public boolean isAuthorized( String principal, String repoId, boolean isWriteRequest ) + public boolean isAuthorized( String principal, String repoId, String permission ) throws UnauthorizedException { return true; diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java index 47a94a9e3..13b8fc871 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java @@ -193,7 +193,7 @@ public class RepositoryServletRepositoryGroupTest WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_INVALID_REPOS + "/" + resourceName ); WebResponse response = sc.getResponse( request ); - assertResponseNotFound( response ); + assertResponseInternalServerError( response ); } /* diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.java index 4d29198a6..f5a33ff49 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.java @@ -32,6 +32,7 @@ import org.apache.jackrabbit.webdav.DavSessionProvider; import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.Configuration; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.apache.maven.archiva.security.ArchivaRoleConstants; import org.apache.maven.archiva.security.ArchivaXworkUser; import org.apache.maven.archiva.security.ServletAuthenticator; import org.codehaus.plexus.redback.authentication.AuthenticationException; @@ -56,9 +57,7 @@ import com.meterware.servletunit.ServletRunner; import com.meterware.servletunit.ServletUnitClient; /** - * RepositoryServletSecurityTest - * - * Test the flow of the authentication and authorization checks. This does not necessarily + * RepositoryServletSecurityTest Test the flow of the authentication and authorization checks. This does not necessarily * perform redback security checking. * * @version $Id$ @@ -87,7 +86,7 @@ public class RepositoryServletSecurityTest private HttpAuthenticator httpAuth; private RepositoryServlet servlet; - + public void setUp() throws Exception { @@ -126,7 +125,7 @@ public class RepositoryServletSecurityTest ArchivaXworkUser archivaXworkUser = (ArchivaXworkUser) lookup( ArchivaXworkUser.class ); - davSessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth, archivaXworkUser ); + davSessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth, archivaXworkUser ); } protected ManagedRepositoryConfiguration createManagedRepository( String id, String name, File location ) @@ -182,11 +181,11 @@ public class RepositoryServletSecurityTest if ( repoRootInternal.exists() ) { - FileUtils.deleteDirectory(repoRootInternal); + FileUtils.deleteDirectory( repoRootInternal ); } servlet = null; - + super.tearDown(); } @@ -209,21 +208,21 @@ public class RepositoryServletSecurityTest AuthenticationResult result = new AuthenticationResult(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ), - new AuthenticationException( "Authentication error" ) ); - - servletAuth.isAuthorized( "guest", "internal", true ); + new AuthenticationException( "Authentication error" ) ); + + servletAuth.isAuthorized( "guest", "internal", ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ); servletAuthControl.setMatcher( MockControl.EQUALS_MATCHER ); servletAuthControl.setThrowable( new UnauthorizedException( "'guest' has no write access to repository" ) ); httpAuthControl.replay(); servletAuthControl.replay(); - + servlet.service( ic.getRequest(), ic.getResponse() ); - + httpAuthControl.verify(); servletAuthControl.verify(); - //assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode()); + // assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode()); } // test deploy with invalid user, but guest has write access to repo @@ -247,30 +246,30 @@ public class RepositoryServletSecurityTest archivaDavResourceFactory.setServletAuth( servletAuth ); servlet.setResourceFactory( archivaDavResourceFactory ); - + AuthenticationResult result = new AuthenticationResult(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ), new AuthenticationException( "Authentication error" ) ); - - servletAuth.isAuthorized( "guest", "internal", true ); + + servletAuth.isAuthorized( "guest", "internal", ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ); servletAuthControl.setMatcher( MockControl.EQUALS_MATCHER ); servletAuthControl.setReturnValue( true ); - - // ArchivaDavResourceFactory#isAuthorized() + + // ArchivaDavResourceFactory#isAuthorized() SecuritySession session = new DefaultSecuritySession(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); - httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true) ), session ); + httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session ); servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, result ), new AuthenticationException( "Authentication error" ) ); - + httpAuthControl.expectAndReturn( httpAuth.getSessionUser( ic.getRequest().getSession() ), null ); - + // check if guest has write access - servletAuth.isAuthorized( "guest", "internal", true ); + servletAuth.isAuthorized( "guest", "internal", ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ); servletAuthControl.setMatcher( MockControl.EQUALS_MATCHER ); servletAuthControl.setReturnValue( true ); - + httpAuthControl.replay(); servletAuthControl.replay(); @@ -291,13 +290,13 @@ public class RepositoryServletSecurityTest String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar"; InputStream is = getClass().getResourceAsStream( "/artifact.jar" ); assertNotNull( "artifact.jar inputstream", is ); - + WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" ); - - InvocationContext ic = sc.newInvocation( request ); + + InvocationContext ic = sc.newInvocation( request ); servlet = (RepositoryServlet) ic.getServlet(); servlet.setDavSessionProvider( davSessionProvider ); - + ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory(); archivaDavResourceFactory.setHttpAuth( httpAuth ); archivaDavResourceFactory.setServletAuth( servletAuth ); @@ -306,23 +305,26 @@ public class RepositoryServletSecurityTest AuthenticationResult result = new AuthenticationResult(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true ); - - // ArchivaDavResourceFactory#isAuthorized() + + // ArchivaDavResourceFactory#isAuthorized() SecuritySession session = new DefaultSecuritySession(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session ); + httpAuthControl.expectAndReturn( httpAuth.getSessionUser( ic.getRequest().getSession() ), new SimpleUser() ); servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true ); - servletAuthControl.expectAndThrow( servletAuth.isAuthorized( null, session, "internal", true ), + servletAuthControl.expectAndThrow( + servletAuth.isAuthorized( null, session, "internal", + ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ), new UnauthorizedException( "User not authorized" ) ); - + httpAuthControl.replay(); servletAuthControl.replay(); - + servlet.service( ic.getRequest(), ic.getResponse() ); httpAuthControl.verify(); servletAuthControl.verify(); - + // assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode()); } @@ -359,7 +361,10 @@ public class RepositoryServletSecurityTest httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session ); httpAuthControl.expectAndReturn( httpAuth.getSessionUser( ic.getRequest().getSession() ), new SimpleUser() ); servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true ); - servletAuthControl.expectAndReturn( servletAuth.isAuthorized( null, session, "internal", true ), true ); + servletAuthControl.expectAndReturn( + servletAuth.isAuthorized( null, session, "internal", + ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ), + true ); httpAuthControl.replay(); servletAuthControl.replay(); @@ -388,7 +393,7 @@ public class RepositoryServletSecurityTest InvocationContext ic = sc.newInvocation( request ); servlet = (RepositoryServlet) ic.getServlet(); servlet.setDavSessionProvider( davSessionProvider ); - + ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory(); archivaDavResourceFactory.setHttpAuth( httpAuth ); archivaDavResourceFactory.setServletAuth( servletAuth ); @@ -399,15 +404,21 @@ public class RepositoryServletSecurityTest httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ), new AuthenticationException( "Authentication error" ) ); - servletAuthControl.expectAndReturn( servletAuth.isAuthorized( "guest", "internal", false ), true ); - - // ArchivaDavResourceFactory#isAuthorized() + servletAuthControl.expectAndReturn( + servletAuth.isAuthorized( "guest", "internal", + ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ), + true ); + + // ArchivaDavResourceFactory#isAuthorized() SecuritySession session = new DefaultSecuritySession(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session ); httpAuthControl.expectAndReturn( httpAuth.getSessionUser( ic.getRequest().getSession() ), null ); servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true ); - servletAuthControl.expectAndReturn( servletAuth.isAuthorized( null, session, "internal", true ), true ); + servletAuthControl.expectAndReturn( + servletAuth.isAuthorized( null, session, "internal", + ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ), + true ); httpAuthControl.replay(); servletAuthControl.replay(); @@ -442,7 +453,10 @@ public class RepositoryServletSecurityTest httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ), new AuthenticationException( "Authentication error" ) ); - servletAuthControl.expectAndReturn( servletAuth.isAuthorized( "guest", "internal", false ), false ); + servletAuthControl.expectAndReturn( + servletAuth.isAuthorized( "guest", "internal", + ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ), + false ); httpAuthControl.replay(); servletAuthControl.replay(); @@ -477,24 +491,27 @@ public class RepositoryServletSecurityTest archivaDavResourceFactory.setServletAuth( servletAuth ); servlet.setResourceFactory( archivaDavResourceFactory ); - + AuthenticationResult result = new AuthenticationResult(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true ); - - // ArchivaDavResourceFactory#isAuthorized() + + // ArchivaDavResourceFactory#isAuthorized() SecuritySession session = new DefaultSecuritySession(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session ); httpAuthControl.expectAndReturn( httpAuth.getSessionUser( ic.getRequest().getSession() ), new SimpleUser() ); servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true ); - servletAuthControl.expectAndReturn( servletAuth.isAuthorized( null, session, "internal", true ), true ); - + servletAuthControl.expectAndReturn( + servletAuth.isAuthorized( null, session, "internal", + ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ), + true ); + httpAuthControl.replay(); servletAuthControl.replay(); WebResponse response = sc.getResponse( request ); - + httpAuthControl.verify(); servletAuthControl.verify(); @@ -524,27 +541,30 @@ public class RepositoryServletSecurityTest archivaDavResourceFactory.setServletAuth( servletAuth ); servlet.setResourceFactory( archivaDavResourceFactory ); - + AuthenticationResult result = new AuthenticationResult(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true ); - // ArchivaDavResourceFactory#isAuthorized() + // ArchivaDavResourceFactory#isAuthorized() SecuritySession session = new DefaultSecuritySession(); httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result ); httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session ); + httpAuthControl.expectAndReturn( httpAuth.getSessionUser( ic.getRequest().getSession() ), new SimpleUser() ); servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true ); - servletAuthControl.expectAndThrow( servletAuth.isAuthorized( null, session, "internal", true ), + servletAuthControl.expectAndThrow( + servletAuth.isAuthorized( null, session, "internal", + ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD ), new UnauthorizedException( "User not authorized to read repository." ) ); - + httpAuthControl.replay(); servletAuthControl.replay(); - + WebResponse response = sc.getResponse( request ); httpAuthControl.verify(); servletAuthControl.verify(); - + assertEquals( HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode() ); } } -- 2.39.5