/*
* soapUI, copyright (C) 2004-2011 eviware.com
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI 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 Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui.security.scan;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.MaliciousAttachmentConfig;
import com.eviware.soapui.config.MaliciousAttachmentElementConfig;
import com.eviware.soapui.config.MaliciousAttachmentSecurityScanConfig;
import com.eviware.soapui.config.SecurityScanConfig;
import com.eviware.soapui.config.StrategyTypeConfig;
import com.eviware.soapui.impl.support.AbstractHttpRequest;
import com.eviware.soapui.impl.wsdl.AttachmentContainer;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.iface.Attachment;
import com.eviware.soapui.model.iface.MessageExchange;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.security.SecurityTestRunContext;
import com.eviware.soapui.security.SecurityTestRunner;
import com.eviware.soapui.security.tools.RandomFile;
import com.eviware.soapui.security.ui.MaliciousAttachmentAdvancedSettingsPanel;
import com.eviware.soapui.security.ui.MaliciousAttachmentMutationsPanel;
import com.eviware.soapui.support.UISupport;
public class MaliciousAttachmentSecurityScan extends AbstractSecurityScan implements PropertyChangeListener
{
public static final String TYPE = "MaliciousAttachmentSecurityScan";
public static final String NAME = "Malicious Attachment";
private MaliciousAttachmentSecurityScanConfig config;
private MaliciousAttachmentAdvancedSettingsPanel advancedSettingsPanel;
private MaliciousAttachmentMutationsPanel mutationsPanel;
private int elementIndex = -1;
private int valueIndex = -1;
private AbstractHttpRequest<?> request;
public MaliciousAttachmentSecurityScan( TestStep testStep, SecurityScanConfig newConfig, ModelItem parent,
String icon )
{
super( testStep, newConfig, parent, icon );
if( newConfig.getConfig() == null || !( newConfig.getConfig() instanceof MaliciousAttachmentSecurityScanConfig ) )
{
initConfig();
}
else
{
config = ( ( MaliciousAttachmentSecurityScanConfig )newConfig.getConfig() );
}
request = ( ( AbstractHttpRequest<?> )getRequest( testStep ) );
request.addAttachmentsChangeListener( this );
}
/**
* Default malicious attachment configuration
*/
protected void initConfig()
{
getConfig().setConfig( MaliciousAttachmentSecurityScanConfig.Factory.newInstance() );
config = ( MaliciousAttachmentSecurityScanConfig )getConfig().getConfig();
}
private void generateFiles()
{
if( config != null )
{
for( MaliciousAttachmentElementConfig element : config.getElementList() )
{
for( MaliciousAttachmentConfig value : element.getGenerateAttachmentList() )
{
File file = new File( value.getFilename() );
try
{
if( !file.exists() || file.length() == 0 )
{
file = new RandomFile( value.getSize(), value.getFilename(), value.getContentType() ).next();
}
}
catch( IOException e )
{
SoapUI.logError( e );
}
}
}
}
}
@Override
public void updateSecurityConfig( SecurityScanConfig config )
{
super.updateSecurityConfig( config );
if( this.config != null )
{
this.config = ( MaliciousAttachmentSecurityScanConfig )getConfig().getConfig();
}
if( advancedSettingsPanel != null )
{
advancedSettingsPanel.setConfig( ( MaliciousAttachmentSecurityScanConfig )getConfig().getConfig() );
}
if( mutationsPanel != null )
{
mutationsPanel.updateConfig( ( MaliciousAttachmentSecurityScanConfig )getConfig().getConfig() );
}
}
public MaliciousAttachmentSecurityScanConfig getMaliciousAttachmentSecurityScanConfig()
{
return config;
}
/*
* Set attachments. Strategy determines the number of existing attachments
* used (one/all)
*/
private void updateRequestContent( TestStep testStep, SecurityTestRunContext context )
{
if( config.getRequestTimeout() > 0 )
{
setRequestTimeout( testStep, config.getRequestTimeout() );
}
if( getExecutionStrategy().getStrategy() == StrategyTypeConfig.ONE_BY_ONE )
{
if( elementIndex == -1 )
{
elementIndex++ ;
}
if( elementIndex < config.getElementList().size() )
{
MaliciousAttachmentElementConfig element = config.getElementList().get( elementIndex );
removeAttachments( testStep, element.getKey(), false );
if( element.getRemove() )
{
removeAttachments( testStep, element.getKey(), true );
}
if( valueIndex < element.getGenerateAttachmentList().size() + element.getReplaceAttachmentList().size() - 1 )
{
valueIndex++ ;
addAttachments( testStep, element, valueIndex );
}
if( valueIndex == element.getGenerateAttachmentList().size() + element.getReplaceAttachmentList().size()
- 1 )
{
valueIndex = -1;
elementIndex++ ;
}
}
}
else if( getExecutionStrategy().getStrategy() == StrategyTypeConfig.ALL_AT_ONCE )
{
if( elementIndex == -1 )
{
elementIndex++ ;
}
executeAllAtOnce( testStep );
valueIndex++ ;
}
}
private void executeAllAtOnce( TestStep testStep )
{
for( MaliciousAttachmentElementConfig element : config.getElementList() )
{
if( element.getRemove() )
{
removeAttachments( testStep, element.getKey(), true );
}
int valIndex = valueIndex;
if( valIndex < element.getGenerateAttachmentList().size() + element.getReplaceAttachmentList().size() - 1 )
{
valIndex++ ;
addAttachments( testStep, element, valIndex );
}
if( valIndex + 1 > element.getGenerateAttachmentList().size() + element.getReplaceAttachmentList().size() - 1 )
{
elementIndex++ ;
}
}
}
private void addAttachments( TestStep testStep, MaliciousAttachmentElementConfig element, int counter )
{
if( counter == -1 )
{
return;
}
boolean generated = false;
List<MaliciousAttachmentConfig> list = null;
if( counter < element.getGenerateAttachmentList().size() )
{
generated = true;
list = element.getGenerateAttachmentList();
}
else
{
list = element.getReplaceAttachmentList();
counter = counter - element.getGenerateAttachmentList().size();
}
MaliciousAttachmentConfig value = list.get( counter );
File file = new File( value.getFilename() );
if( value.getEnabled() )
{
try
{
if( !file.exists() )
{
UISupport.showErrorMessage( "Missing file: " + file.getName() );
return;
}
addAttachment( testStep, file, value.getContentType(), generated, value.getCached() );
}
catch( IOException e )
{
SoapUI.logError( e );
}
}
}
@Override
protected void execute( SecurityTestRunner securityTestRunner, TestStep testStep, SecurityTestRunContext context )
{
try
{
request.removeAttachmentsChangeListener( this );
generateFiles();
updateRequestContent( testStep, context );
MessageExchange message = ( MessageExchange )testStep.run( ( TestCaseRunner )securityTestRunner, context );
getSecurityScanRequestResult().setMessageExchange( message );
request.addAttachmentsChangeListener( this );
}
catch( Exception e )
{
SoapUI.logError( e, "[MaliciousAttachmentSecurityScan]Property value is not valid xml!" );
reportSecurityScanException( "Property value is not XML or XPath is wrong!" );
}
}
@Override
public String getType()
{
return TYPE;
}
private Attachment addAttachment( TestStep testStep, File file, String contentType, boolean generated, boolean cache )
throws IOException
{
AbstractHttpRequest<?> request = ( AbstractHttpRequest<?> )getRequest( testStep );
Attachment attach = request.attachFile( file, cache );
attach.setContentType( contentType );
return attach;
}
private void removeAttachments( TestStep testStep, String key, boolean equals )
{
List<Attachment> toRemove = new ArrayList<Attachment>();
AbstractHttpRequest<?> request = ( AbstractHttpRequest<?> )getRequest( testStep );
for( Attachment attachment : request.getAttachments() )
{
if( equals )
{
if( attachment.getId().equals( key ) )
{
toRemove.add( attachment );
}
}
else
{
if( !attachment.getId().equals( key ) )
{
toRemove.add( attachment );
}
}
}
for( Attachment remove : toRemove )
{
request.removeAttachment( remove );
}
}
private void setRequestTimeout( TestStep testStep, int timeout )
{
AbstractHttpRequest<?> request = ( AbstractHttpRequest<?> )getRequest( testStep );
request.setTimeout( String.valueOf( timeout ) );
}
@Override
public JComponent getComponent()
{
if( mutationsPanel == null )
mutationsPanel = new MaliciousAttachmentMutationsPanel( config,
( AbstractHttpRequest<?> )getRequest( getTestStep() ) );
return mutationsPanel.getPanel();
}
@Override
protected boolean hasNext( TestStep testStep, SecurityTestRunContext context )
{
AbstractHttpRequest<?> request = ( AbstractHttpRequest<?> )getRequest( testStep );
boolean hasNext = request.getAttachmentCount() == 0 ? false : elementIndex < config.getElementList().size();
if( !hasNext )
{
elementIndex = -1;
valueIndex = -1;
}
return hasNext;
}
@Override
public String getConfigDescription()
{
return "Configures malicious attachment security scan";
}
@Override
public String getConfigName()
{
return "Malicious Attachment Security Scan";
}
@Override
public String getHelpURL()
{
return "http://soapui.org/Security/malicious-attachment.html";
}
@Override
public JComponent getAdvancedSettingsPanel()
{
if( advancedSettingsPanel == null )
advancedSettingsPanel = new MaliciousAttachmentAdvancedSettingsPanel( config );
return advancedSettingsPanel.getPanel();
}
@Override
public void copyConfig( SecurityScanConfig config )
{
super.copyConfig( config );
if( advancedSettingsPanel != null )
{
advancedSettingsPanel.setConfig( ( MaliciousAttachmentSecurityScanConfig )getConfig().getConfig() );
}
if( mutationsPanel != null )
{
mutationsPanel.updateConfig( ( MaliciousAttachmentSecurityScanConfig )getConfig().getConfig() );
}
}
@Override
public void release()
{
if( advancedSettingsPanel != null )
advancedSettingsPanel.release();
if( mutationsPanel != null )
mutationsPanel.release();
if( request != null )
request.removeAttachmentsChangeListener( this );
super.release();
}
private void addedAttachment( Attachment attachment )
{
if( config != null )
{
MaliciousAttachmentElementConfig element = config.addNewElement();
element.setKey( attachment.getId() );
}
}
private void removedAttachment( Attachment attachment )
{
if( config != null )
{
int idx = -1;
for( int i = 0; i < config.getElementList().size(); i++ )
{
MaliciousAttachmentElementConfig element = config.getElementList().get( i );
if( attachment.getId().equals( element.getKey() ) )
{
idx = i;
break;
}
}
if( idx != -1 )
{
config.removeElement( idx );
}
}
if( mutationsPanel != null )
{
mutationsPanel.getHolder().removeAttachment( attachment.getId() );
}
}
@Override
public void propertyChange( PropertyChangeEvent evt )
{
if( AttachmentContainer.ATTACHMENTS_PROPERTY.equals( evt.getPropertyName() ) )
{
if( evt.getOldValue() == null && evt.getNewValue() != null )
{
if( evt.getNewValue() instanceof Attachment )
{
Attachment attachment = ( Attachment )evt.getNewValue();
addedAttachment( attachment );
}
}
else if( evt.getOldValue() != null && evt.getNewValue() == null )
{
if( evt.getOldValue() instanceof Attachment )
{
Attachment attachment = ( Attachment )evt.getOldValue();
removedAttachment( attachment );
}
}
}
}
}