/** * Copyright (c) 2008-2011 Sonatype, Inc. * All rights reserved. Includes the third-party code listed at http://www.sonatype.com/products/nexus/attributions. * * This program is free software: you can redistribute it and/or modify it only under the terms of the GNU Affero General * Public License Version 3 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License Version 3 * for more details. * * You should have received a copy of the GNU Affero General Public License Version 3 along with this program. If not, see * http://www.gnu.org/licenses. * * Sonatype Nexus (TM) Open Source Version is available from Sonatype, Inc. Sonatype and Sonatype Nexus are trademarks of * Sonatype, Inc. Apache Maven is a trademark of the Apache Foundation. M2Eclipse is a trademark of the Eclipse Foundation. * All other trademarks are the property of their respective owners. */ package org.sonatype.nexus.security.filter.authz; import java.io.IOException; import java.util.regex.Matcher; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import org.apache.shiro.web.util.WebUtils; import org.sonatype.nexus.proxy.AccessDeniedException; import org.sonatype.nexus.proxy.ItemNotFoundException; import org.sonatype.nexus.proxy.RequestContext; import org.sonatype.nexus.proxy.ResourceStoreRequest; import org.sonatype.nexus.proxy.access.Action; /** * A filter that maps the targetId from the Request. * * @author cstamas */ public class NexusTargetMappingAuthorizationFilter extends AbstractNexusAuthorizationFilter { private String pathReplacement; public String getPathReplacement() { if ( pathReplacement == null ) { pathReplacement = ""; } return pathReplacement; } public void setPathReplacement( String pathReplacement ) { this.pathReplacement = pathReplacement; } public String getResourceStorePath( ServletRequest request ) { String path = WebUtils.getPathWithinApplication( (HttpServletRequest) request ); if ( getPathPrefix() != null ) { Matcher m = this.getPathPrefixPattern().matcher( path ); if ( m.matches() ) { path = getPathReplacement(); // TODO: hardcoded currently if ( path.contains( "@1" ) ) { path = path.replaceAll( "@1", Matcher.quoteReplacement( m.group( 1 ) ) ); } if ( path.contains( "@2" ) ) { path = path.replaceAll( "@2", Matcher.quoteReplacement( m.group( 2 ) ) ); } // and so on... this will be reworked to be dynamic } else { throw new IllegalArgumentException( "The request path does not matches the incoming request? This is misconfiguration in web.xml!" ); } } return path; } protected ResourceStoreRequest getResourceStoreRequest( ServletRequest request, boolean localOnly ) { ResourceStoreRequest rsr = new ResourceStoreRequest( getResourceStorePath( request ), localOnly ); rsr.getRequestContext().put( RequestContext.CTX_AUTH_CHECK_ONLY, true ); return rsr; } @Override protected String getHttpMethodAction(ServletRequest request) { String method = ((HttpServletRequest) request).getMethod().toLowerCase(); if ( "put".equals( method ) ) { // heavy handed thing // doing a LOCAL ONLY request to check is this exists? try { getNexus( request ).getRootRouter().retrieveItem( getResourceStoreRequest( request, true ) ); } catch ( ItemNotFoundException e ) { // the path does not exists, it is a CREATE method = "post"; } catch ( AccessDeniedException e ) { // no access for read, so chances are post or put doesnt matter method = "post"; } catch ( Exception e ) { // huh? throw new IllegalStateException( "Got exception during target mapping!", e ); } // the path exists, this is UPDATE return super.getHttpMethodAction( method ); } else { return super.getHttpMethodAction( request ); } } @Override public boolean isAccessAllowed( ServletRequest request, ServletResponse response, Object mappedValue ) throws IOException { // let check the mappedValues 1st boolean result = false; if ( mappedValue != null ) { result = super.isAccessAllowed( request, response, mappedValue ); // if we are not allowed at start, forbid it if ( !result ) { return false; } } String actionVerb = getHttpMethodAction( request ); Action action = Action.valueOf( actionVerb ); if ( null == action ) { return false; } return this.getRepositoryRouter().authorizePath( getResourceStoreRequest( request, false ), action ); } }