View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.submit.filters;
14  
15  import java.io.IOException;
16  
17  import org.apache.ws.security.WSConstants;
18  import org.apache.ws.security.WSSConfig;
19  import org.apache.ws.security.message.WSSecHeader;
20  import org.apache.ws.security.message.WSSecTimestamp;
21  import org.apache.ws.security.message.WSSecUsernameToken;
22  import org.w3c.dom.Document;
23  import org.w3c.dom.Element;
24  import org.xml.sax.SAXException;
25  
26  import com.eviware.soapui.SoapUI;
27  import com.eviware.soapui.impl.wsdl.WsdlRequest;
28  import com.eviware.soapui.model.iface.SubmitContext;
29  import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
30  import com.eviware.soapui.support.StringUtils;
31  import com.eviware.soapui.support.xml.XmlUtils;
32  
33  /***
34   * Modifies the request message to include WS-Securty Username and Timestamp
35   * tokens
36   * 
37   * @author Ole.Matzura
38   */
39  
40  public class WssAuthenticationRequestFilter extends AbstractWssRequestFilter
41  {
42  	private static final String WSS_USERNAME_TOKEN = "WsSecurityAuthenticationRequestFilter@UsernameToken";
43  	private static final String WSS_TIMESTAMP_TOKEN = "WsSecurityAuthenticationRequestFilter@TimestampToken";
44  
45  	public void filterWsdlRequest( SubmitContext context, WsdlRequest wsdlRequest )
46  	{
47  		String pwType = PropertyExpander.expandProperties( context, wsdlRequest.getWssPasswordType() );
48  		String wsTimestamp = wsdlRequest.getWssTimeToLive();
49  
50  		if( ( StringUtils.isNullOrEmpty( pwType ) || WsdlRequest.PW_TYPE_NONE.equals( pwType ) )
51  				&& ( StringUtils.isNullOrEmpty( wsTimestamp ) ) )
52  			return;
53  		try
54  		{
55  			String password = PropertyExpander.expandProperties( context, wsdlRequest.getPassword() );
56  			String username = PropertyExpander.expandProperties( context, wsdlRequest.getUsername() );
57  
58  			setWssHeaders( context, username, password, pwType, wsTimestamp );
59  		}
60  		catch( Throwable e )
61  		{
62  			SoapUI.logError( e );
63  		}
64  	}
65  
66  	public static void setWssHeaders( SubmitContext context, String username, String password, String pwType,
67  			String wsTimestamp ) throws SAXException, IOException
68  	{
69  		Document doc = getWssDocument( context );
70  
71  		// create username token?
72  		if( StringUtils.hasContent( pwType ) && !pwType.equals( WsdlRequest.PW_TYPE_NONE )
73  				&& StringUtils.hasContent( username ) && StringUtils.hasContent( password ) )
74  		{
75  			// remove if already set
76  			Element elm = ( Element )context.getProperty( WSS_USERNAME_TOKEN );
77  			if( elm != null )
78  			{
79  				Element parentNode = ( Element )elm.getParentNode();
80  				parentNode.removeChild( elm );
81  			}
82  
83  			// save it so it can be removed..
84  			context.setProperty( WSS_USERNAME_TOKEN, setWssUsernameToken( username, password, pwType, doc ) );
85  		}
86  		// remove if pwType is not null
87  		else if( pwType != null && context.getProperty( WSS_USERNAME_TOKEN ) != null )
88  		{
89  			Element elm = ( Element )context.getProperty( WSS_USERNAME_TOKEN );
90  			context.removeProperty( WSS_USERNAME_TOKEN );
91  			Element parentNode = ( Element )elm.getParentNode();
92  			parentNode.removeChild( elm );
93  			if( XmlUtils.getChildElements( parentNode ).getLength() == 0 )
94  				parentNode.getParentNode().removeChild( parentNode );
95  		}
96  
97  		// add timestamp?
98  		if( StringUtils.hasContent( wsTimestamp ) )
99  		{
100 			// remove if already set
101 			Element elm = ( Element )context.getProperty( WSS_TIMESTAMP_TOKEN );
102 			if( elm != null )
103 			{
104 				Element parentNode = ( Element )elm.getParentNode();
105 				parentNode.removeChild( elm );
106 			}
107 
108 			// save it so it can be removed..
109 			context.setProperty( WSS_TIMESTAMP_TOKEN, setWsTimestampToken( wsTimestamp, doc ) );
110 		}
111 		// remove
112 		else if( wsTimestamp != null && context.getProperty( WSS_TIMESTAMP_TOKEN ) != null )
113 		{
114 			Element elm = ( Element )context.getProperty( WSS_TIMESTAMP_TOKEN );
115 			context.removeProperty( WSS_TIMESTAMP_TOKEN );
116 			Element parentNode = ( Element )elm.getParentNode();
117 			parentNode.removeChild( elm );
118 			if( XmlUtils.getChildElements( parentNode ).getLength() == 0 )
119 				parentNode.getParentNode().removeChild( parentNode );
120 		}
121 
122 		updateWssDocument( context, doc );
123 	}
124 
125 	private static Element setWsTimestampToken( String ttl, Document doc )
126 	{
127 		WSSecTimestamp addTimestamp = new WSSecTimestamp();
128 		addTimestamp.setTimeToLive( Integer.parseInt( ttl ) );
129 
130 		WSSConfig wsc = WSSConfig.getNewInstance();
131 		wsc.setPrecisionInMilliSeconds( false );
132 		wsc.setTimeStampStrict( false );
133 		addTimestamp.setWsConfig( wsc );
134 
135 		WSSecHeader secHeader = new WSSecHeader();
136 		secHeader.insertSecurityHeader( doc );
137 		addTimestamp.build( doc, secHeader );
138 		return addTimestamp.getElement();
139 	}
140 
141 	private static Element setWssUsernameToken( String username, String password, String pwType, Document doc )
142 	{
143 		WSSecUsernameToken wsa = new WSSecUsernameToken();
144 		if( WsdlRequest.PW_TYPE_DIGEST.equals( pwType ) )
145 		{
146 			wsa.setPasswordType( WSConstants.PASSWORD_DIGEST );
147 		}
148 		else
149 		{
150 			wsa.setPasswordType( WSConstants.PASSWORD_TEXT );
151 		}
152 
153 		wsa.setUserInfo( username, password );
154 		wsa.addNonce();
155 		wsa.addCreated();
156 
157 		WSSecHeader secHeader = new WSSecHeader();
158 		secHeader.insertSecurityHeader( doc );
159 		wsa.build( doc, secHeader );
160 		return wsa.getUsernameTokenElement();
161 	}
162 }