blob: cf8dc71452f1c2c1931a060d1355ad6510d51bdd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.axis2.transport.http;
import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.Parameter;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import javax.xml.namespace.QName;
import java.net.URL;
import java.util.StringTokenizer;
/**
* The purpose of this class is to configure the proxy auth regardles of the protocol.
* Proxy will be set only for HTTP connection
*/
public class ProxyConfiguration {
protected String proxyHost;
protected String nonProxyHosts;
protected int proxyPort = -1; //If port is not set, default is set to -1
protected String proxyUser;
protected String proxyPassword;
protected static final String HTTP_PROXY_HOST = "http.proxyHost";
protected static final String HTTP_PROXY_PORT = "http.proxyPort";
protected static final String HTTP_NON_PROXY_HOSTS = "http.nonProxyHosts";
protected static final String ATTR_PROXY = "Proxy";
protected static final String PROXY_HOST_ELEMENT = "ProxyHost";
protected static final String PROXY_PORT_ELEMENT = "ProxyPort";
protected static final String PROXY_USER_ELEMENT = "ProxyUser";
protected static final String PROXY_PASSWORD_ELEMENT = "ProxyPassword";
public void configure(MessageContext messageContext,
HttpClient httpClient,
HostConfiguration config) throws AxisFault {
// <parameter name="Proxy">
// <Configuration>
// <ProxyHost>example.org</ProxyHost>
// <ProxyPort>5678</ProxyPort>
// <ProxyUser>EXAMPLE\saminda</ProxyUser>
// <ProxyPassword>ppp</ProxyPassword>
// </Configuration>
// </parameter>
Credentials proxyCred = null;
//Getting configuration values from Axis2.xml
Parameter param = messageContext.getConfigurationContext().getAxisConfiguration()
.getParameter(ATTR_PROXY);
if (param != null) {
OMElement configurationEle = param.getParameterElement().getFirstElement();
if (configurationEle == null) {
throw new AxisFault(
ProxyConfiguration.class.getName() + " Configuration element is missing");
}
OMElement proxyHostEle =
configurationEle.getFirstChildWithName(new QName(PROXY_HOST_ELEMENT));
OMElement proxyPortEle =
configurationEle.getFirstChildWithName(new QName(PROXY_PORT_ELEMENT));
OMElement proxyUserEle =
configurationEle.getFirstChildWithName(new QName(PROXY_USER_ELEMENT));
OMElement proxyPasswordEle =
configurationEle.getFirstChildWithName(new QName(PROXY_PASSWORD_ELEMENT));
if (proxyHostEle == null) {
throw new AxisFault(
ProxyConfiguration.class.getName() + " ProxyHost element is missing");
}
String text = proxyHostEle.getText();
if (text == null) {
throw new AxisFault(
ProxyConfiguration.class.getName() + " ProxyHost's value is missing");
}
this.setProxyHost(text);
if (proxyPortEle != null) {
this.setProxyPort(Integer.parseInt(proxyPortEle.getText()));
}
if (proxyUserEle != null) {
this.setProxyUser(proxyUserEle.getText());
}
if (proxyPasswordEle != null) {
this.setProxyPassword(proxyPasswordEle.getText());
}
if (this.getProxyUser() == null && this.getProxyUser() == null) {
proxyCred = new UsernamePasswordCredentials("", "");
} else {
proxyCred =
new UsernamePasswordCredentials(this.getProxyUser(),
this.getProxyPassword());
}
// if the username is in the form "DOMAIN\\user"
// then use NTCredentials instead.
if (this.getProxyUser() != null) {
int domainIndex = this.getProxyUser().indexOf("\\");
if (domainIndex > 0) {
String domain = this.getProxyUser().substring(0, domainIndex);
if (this.getProxyUser().length() > domainIndex + 1) {
String user = this.getProxyUser().substring(domainIndex + 1);
proxyCred = new NTCredentials(user,
this.getProxyPassword(),
this.getProxyHost(),
domain);
}
}
}
}
// Overide the property setting in runtime.
HttpTransportProperties.ProxyProperties proxyProperties =
(HttpTransportProperties.ProxyProperties) messageContext
.getProperty(HTTPConstants.PROXY);
if (proxyProperties != null) {
String host = proxyProperties.getProxyHostName();
if (host == null || host.length() == 0) {
throw new AxisFault(ProxyConfiguration.class.getName() +
" Proxy host is not available. Host is a MUST parameter");
} else {
this.setProxyHost(host);
}
this.setProxyPort(proxyProperties.getProxyPort());
//Setting credentials
String userName = proxyProperties.getUserName();
String password = proxyProperties.getPassWord();
String domain = proxyProperties.getDomain();
if (userName == null && password == null) {
proxyCred = new UsernamePasswordCredentials("", "");
} else {
proxyCred = new UsernamePasswordCredentials(userName, password);
}
if (userName != null && password != null && domain != null) {
proxyCred = new NTCredentials(userName, password, host, domain);
}
}
//Using Java Networking Properties
String host = System.getProperty(HTTP_PROXY_HOST);
if (host != null) {
this.setProxyHost(host);
proxyCred = new UsernamePasswordCredentials("","");
}
String port = System.getProperty(HTTP_PROXY_PORT);
if (port != null) {
this.setProxyPort(Integer.parseInt(port));
}
if (proxyCred == null) {
throw new AxisFault(ProxyConfiguration.class.getName() +
" Minimum proxy credentials are not set");
}
httpClient.getParams().setAuthenticationPreemptive(true);
httpClient.getState().setProxyCredentials(AuthScope.ANY, proxyCred);
config.setProxy(this.getProxyHost(), this.getProxyPort());
}
/**
* Check first if the proxy is configured or active.
* If yes this will return true. This is not a deep check
*
* @param messageContext
* @return boolean
*/
public static boolean isProxyEnabled(MessageContext messageContext, URL targetURL)
throws AxisFault {
boolean state = false;
Parameter param = messageContext.getConfigurationContext().getAxisConfiguration()
.getParameter(ATTR_PROXY);
//If configuration is over ridden
Object obj = messageContext.getProperty(HTTPConstants.PROXY);
//From Java Networking Properties
String sp = System.getProperty(HTTP_PROXY_HOST);
if (param != null || obj != null || sp != null) {
state = true;
}
boolean isNonProxyHost = validateNonProxyHosts(targetURL.getHost());
return state && !isNonProxyHost;
}
/**
* Validates for names that shouldn't be listered as proxies.
* The http.nonProxyHosts can be set to specify the hosts which should be
* connected to directly (not through the proxy server).
* The value of the http.nonProxyHosts property can be a list of hosts,
* each separated by a |; it can also take a regular expression for matches;
* for example: *.sfbay.sun.com would match any fully qualified hostname in the sfbay domain.
*
* For more information refer to : http://java.sun.com/features/2002/11/hilevel_network.html
*
* false : validation fail : User can use the proxy
* true : validation pass ; User can't use the proxy
*
* @return boolean
*/
public static boolean validateNonProxyHosts(String host) {
//From system property http.nonProxyHosts
String nonProxyHosts = System.getProperty(HTTP_NON_PROXY_HOSTS);
return isHostInNonProxyList(host, nonProxyHosts);
}
/**
* Check if the specified host is in the list of non proxy hosts.
*
* @param host host name
* @param nonProxyHosts string containing the list of non proxy hosts
*
* @return true/false
*/
public static boolean isHostInNonProxyList(String host, String nonProxyHosts) {
if ((nonProxyHosts == null) || (host == null)) {
return false;
}
/*
* The http.nonProxyHosts system property is a list enclosed in
* double quotes with items separated by a vertical bar.
*/
StringTokenizer tokenizer = new StringTokenizer(nonProxyHosts, "|\"");
while (tokenizer.hasMoreTokens()) {
String pattern = tokenizer.nextToken();
if (match(pattern, host, false)) {
return true;
}
}
return false;
}
/**
* Matches a string against a pattern. The pattern contains two special
* characters:
* '*' which means zero or more characters,
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the
* pattern
* @param isCaseSensitive
*
* @return <code>true</code> when the string matches against the pattern,
* <code>false</code> otherwise.
*/
protected static boolean match(String pattern, String str,
boolean isCaseSensitive) {
char[] patArr = pattern.toCharArray();
char[] strArr = str.toCharArray();
int patIdxStart = 0;
int patIdxEnd = patArr.length - 1;
int strIdxStart = 0;
int strIdxEnd = strArr.length - 1;
char ch;
boolean containsStar = false;
for (int i = 0; i < patArr.length; i++) {
if (patArr[i] == '*') {
containsStar = true;
break;
}
}
if (!containsStar) {
// No '*'s, so we make a shortcut
if (patIdxEnd != strIdxEnd) {
return false; // Pattern and string do not have the same size
}
for (int i = 0; i <= patIdxEnd; i++) {
ch = patArr[i];
if (isCaseSensitive && (ch != strArr[i])) {
return false; // Character mismatch
}
if (!isCaseSensitive
&& (Character.toUpperCase(ch)
!= Character.toUpperCase(strArr[i]))) {
return false; // Character mismatch
}
}
return true; // String matches against pattern
}
if (patIdxEnd == 0) {
return true; // Pattern contains only '*', which matches anything
}
// Process characters before first star
while ((ch = patArr[patIdxStart]) != '*'
&& (strIdxStart <= strIdxEnd)) {
if (isCaseSensitive && (ch != strArr[strIdxStart])) {
return false; // Character mismatch
}
if (!isCaseSensitive
&& (Character.toUpperCase(ch)
!= Character.toUpperCase(strArr[strIdxStart]))) {
return false; // Character mismatch
}
patIdxStart++;
strIdxStart++;
}
if (strIdxStart > strIdxEnd) {
// All characters in the string are used. Check if only '*'s are
// left in the pattern. If so, we succeeded. Otherwise failure.
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
return false;
}
}
return true;
}
// Process characters after last star
while ((ch = patArr[patIdxEnd]) != '*' && (strIdxStart <= strIdxEnd)) {
if (isCaseSensitive && (ch != strArr[strIdxEnd])) {
return false; // Character mismatch
}
if (!isCaseSensitive
&& (Character.toUpperCase(ch)
!= Character.toUpperCase(strArr[strIdxEnd]))) {
return false; // Character mismatch
}
patIdxEnd--;
strIdxEnd--;
}
if (strIdxStart > strIdxEnd) {
// All characters in the string are used. Check if only '*'s are
// left in the pattern. If so, we succeeded. Otherwise failure.
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
return false;
}
}
return true;
}
// process pattern between stars. padIdxStart and patIdxEnd point
// always to a '*'.
while ((patIdxStart != patIdxEnd) && (strIdxStart <= strIdxEnd)) {
int patIdxTmp = -1;
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
if (patArr[i] == '*') {
patIdxTmp = i;
break;
}
}
if (patIdxTmp == patIdxStart + 1) {
// Two stars next to each other, skip the first one.
patIdxStart++;
continue;
}
// Find the pattern between padIdxStart & padIdxTmp in str between
// strIdxStart & strIdxEnd
int patLength = (patIdxTmp - patIdxStart - 1);
int strLength = (strIdxEnd - strIdxStart + 1);
int foundIdx = -1;
strLoop:
for (int i = 0; i <= strLength - patLength; i++) {
for (int j = 0; j < patLength; j++) {
ch = patArr[patIdxStart + j + 1];
if (isCaseSensitive
&& (ch != strArr[strIdxStart + i + j])) {
continue strLoop;
}
if (!isCaseSensitive && (Character
.toUpperCase(ch) != Character
.toUpperCase(strArr[strIdxStart + i + j]))) {
continue strLoop;
}
}
foundIdx = strIdxStart + i;
break;
}
if (foundIdx == -1) {
return false;
}
patIdxStart = patIdxTmp;
strIdxStart = foundIdx + patLength;
}
// All characters in the string are used. Check if only '*'s are left
// in the pattern. If so, we succeeded. Otherwise failure.
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
return false;
}
}
return true;
}
/**
* Retrun proxy host
*
* @return String
*/
public String getProxyHost() {
return proxyHost;
}
/**
* set proxy host
*
* @param proxyHost
*/
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
/**
* retrun proxy port
*
* @return String
*/
public int getProxyPort() {
return proxyPort;
}
/**
* set proxy port
*
* @param proxyPort
*/
public void setProxyPort(int proxyPort) {
this.proxyPort = proxyPort;
}
/**
* return proxy user. Proxy user can be user/domain or user
*
* @return String
*/
public String getProxyUser() {
return proxyUser;
}
/**
* get proxy user
*
* @param proxyUser
*/
public void setProxyUser(String proxyUser) {
this.proxyUser = proxyUser;
}
/**
* set password
*
* @return String
*/
public String getProxyPassword() {
return proxyPassword;
}
/**
* get password
*
* @param proxyPassword
*/
public void setProxyPassword(String proxyPassword) {
this.proxyPassword = proxyPassword;
}
}