View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 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  import java.io.StringWriter;
17  
18  import org.apache.ws.security.WSConstants;
19  import org.apache.ws.security.WSSConfig;
20  import org.apache.ws.security.message.WSSecHeader;
21  import org.apache.ws.security.message.WSSecTimestamp;
22  import org.apache.ws.security.message.WSSecUsernameToken;
23  import org.w3c.dom.Document;
24  import org.w3c.dom.Element;
25  import org.xml.sax.SAXException;
26  
27  import com.eviware.soapui.SoapUI;
28  import com.eviware.soapui.impl.wsdl.WsdlRequest;
29  import com.eviware.soapui.impl.wsdl.submit.transports.http.BaseHttpRequestTransport;
30  import com.eviware.soapui.model.iface.SubmitContext;
31  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
32  import com.eviware.soapui.support.StringUtils;
33  import com.eviware.soapui.support.xml.XmlUtils;
34  
35  /***
36   * Modifies the request message to include WS-Securty Username and Timestamp tokens
37   * 
38   * @author Ole.Matzura
39   */
40  
41  public class WssAuthenticationRequestFilter extends AbstractWssRequestFilter
42  {
43  	private static final String WSS_USERNAME_TOKEN = "WsSecurityAuthenticationRequestFilter@UsernameToken";
44  	private static final String WSS_TIMESTAMP_TOKEN = "WsSecurityAuthenticationRequestFilter@TimestampToken";
45  
46  	public void filterWsdlRequest(SubmitContext context, WsdlRequest wsdlRequest)
47  	{
48  		String pwType = PropertyExpansionUtils.expandProperties( context, wsdlRequest.getWssPasswordType());
49        String wsTimestamp = wsdlRequest.getWssTimeToLive();
50        
51  		if (  (StringUtils.isNullOrEmpty( pwType ) || WsdlRequest.PW_TYPE_NONE.equals(pwType)) &&
52        		(StringUtils.isNullOrEmpty( wsTimestamp )))
53        		return;
54        try 
55        {
56        	String password = PropertyExpansionUtils.expandProperties( context, wsdlRequest.getPassword() );
57        	String username = PropertyExpansionUtils.expandProperties( context, wsdlRequest.getUsername());
58        	
59          	setWssHeaders( context, username, password, pwType, wsTimestamp );
60        } 
61  		catch (Throwable e) 
62  		{
63            SoapUI.logError( e );
64        }
65  	}
66  
67  	public static void setWssHeaders( SubmitContext context, String username, String password, String pwType, 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 		StringWriter writer = new StringWriter();
123 		XmlUtils.serializePretty( doc, writer );
124 		context.setProperty( BaseHttpRequestTransport.REQUEST_CONTENT, writer.toString() );
125 	}
126 
127 	private static Element setWsTimestampToken( String ttl, Document doc )
128 	{
129 		WSSecTimestamp addTimestamp = new WSSecTimestamp();
130 		addTimestamp.setTimeToLive( Integer.parseInt( ttl ));
131 		
132 		WSSConfig wsc = WSSConfig.getNewInstance();
133 	   wsc.setPrecisionInMilliSeconds(false);
134 	   wsc.setTimeStampStrict(false);
135 	   addTimestamp.setWsConfig(wsc);
136 		
137 		WSSecHeader secHeader = new WSSecHeader();
138 		secHeader.insertSecurityHeader( doc );
139 		addTimestamp.build( doc, secHeader );
140 		return addTimestamp.getElement();
141 	}
142 
143 	private static Element setWssUsernameToken( String username, String password, String pwType, Document doc )
144 	{
145 		WSSecUsernameToken wsa = new WSSecUsernameToken();
146 		if (WsdlRequest.PW_TYPE_DIGEST.equals(pwType)) 
147 		{
148 		   wsa.setPasswordType(WSConstants.PASSWORD_DIGEST);
149 		} 
150 		else 
151 		{
152 		   wsa.setPasswordType(WSConstants.PASSWORD_TEXT);
153 		}
154 		
155 		wsa.setUserInfo(username, password ); 
156 		wsa.addNonce();
157 		wsa.addCreated();
158 		
159 		WSSecHeader secHeader = new WSSecHeader();
160 		secHeader.insertSecurityHeader( doc );
161 		wsa.build(doc, secHeader );
162 		return wsa.getUsernameTokenElement();
163 	}
164 }