Moved HttpClient contrib to new location
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1396241 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
43d4e8f469
commit
e38de5d125
Binary file not shown.
|
@ -1,80 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
====================================================================
|
||||
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.
|
||||
====================================================================
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals on behalf of the Apache Software Foundation. For more
|
||||
information on the Apache Software Foundation, please see
|
||||
<http://www.apache.org />.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcomponents-client</artifactId>
|
||||
<version>4.3-alpha1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>httpclient-contrib</artifactId>
|
||||
<name>HttpClient Contrib</name>
|
||||
<description>
|
||||
HttpComponents HttpClient - Contributed Components
|
||||
</description>
|
||||
<url>http://hc.apache.org/httpcomponents-client</url>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${pom.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15</artifactId>
|
||||
<version>1.45</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<maven.compile.source>1.5</maven.compile.source>
|
||||
<maven.compile.target>1.5</maven.compile.target>
|
||||
<maven.compile.optimize>true</maven.compile.optimize>
|
||||
<maven.compile.deprecation>true</maven.compile.deprecation>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compile.source}</source>
|
||||
<target>${maven.compile.target}</target>
|
||||
<optimize>${maven.compile.optimize}</optimize>
|
||||
<showDeprecations>${maven.compile.deprecation}</showDeprecations>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,254 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.contrib.auth;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Date;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.impl.cookie.DateUtils;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
|
||||
/**
|
||||
* Implementation of Amazon S3 authentication. This scheme must be used
|
||||
* preemptively only.
|
||||
* <p>
|
||||
* Reference Document: {@link http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/latest/index
|
||||
* .html?RESTAuthentication.html}
|
||||
*/
|
||||
public class AWSScheme implements AuthScheme {
|
||||
|
||||
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
|
||||
public static final String NAME = "AWS";
|
||||
|
||||
public AWSScheme() {
|
||||
}
|
||||
|
||||
public Header authenticate(
|
||||
final Credentials credentials,
|
||||
final HttpRequest request) throws AuthenticationException {
|
||||
// If the Date header has not been provided add it as it is required
|
||||
if (request.getFirstHeader("Date") == null) {
|
||||
Header dateHeader = new BasicHeader("Date", DateUtils.formatDate(new Date()));
|
||||
request.addHeader(dateHeader);
|
||||
}
|
||||
|
||||
String canonicalizedAmzHeaders = getCanonicalizedAmzHeaders(request.getAllHeaders());
|
||||
String canonicalizedResource = getCanonicalizedResource(request.getRequestLine().getUri(),
|
||||
(request.getFirstHeader("Host") != null ? request.getFirstHeader("Host").getValue()
|
||||
: null));
|
||||
String contentMD5 = request.getFirstHeader("Content-MD5") != null ? request.getFirstHeader(
|
||||
"Content-MD5").getValue() : "";
|
||||
String contentType = request.getFirstHeader("Content-Type") != null ? request
|
||||
.getFirstHeader("Content-Type").getValue() : "";
|
||||
String date = request.getFirstHeader("Date").getValue();
|
||||
String method = request.getRequestLine().getMethod();
|
||||
|
||||
StringBuilder toSign = new StringBuilder();
|
||||
toSign.append(method).append("\n");
|
||||
toSign.append(contentMD5).append("\n");
|
||||
toSign.append(contentType).append("\n");
|
||||
toSign.append(date).append("\n");
|
||||
toSign.append(canonicalizedAmzHeaders);
|
||||
toSign.append(canonicalizedResource);
|
||||
|
||||
String signature = calculateRFC2104HMAC(toSign.toString(), credentials.getPassword());
|
||||
|
||||
String headerValue = NAME + " " + credentials.getUserPrincipal().getName() + ":" + signature.trim();
|
||||
|
||||
return new BasicHeader("Authorization", headerValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes RFC 2104-compliant HMAC signature.
|
||||
*
|
||||
* @param data
|
||||
* The data to be signed.
|
||||
* @param key
|
||||
* The signing key.
|
||||
* @return The Base64-encoded RFC 2104-compliant HMAC signature.
|
||||
* @throws RuntimeException
|
||||
* when signature generation fails
|
||||
*/
|
||||
private static String calculateRFC2104HMAC(
|
||||
final String data,
|
||||
final String key) throws AuthenticationException {
|
||||
try {
|
||||
// get an hmac_sha1 key from the raw key bytes
|
||||
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
|
||||
|
||||
// get an hmac_sha1 Mac instance and initialize with the signing key
|
||||
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
|
||||
mac.init(signingKey);
|
||||
|
||||
// compute the hmac on input data bytes
|
||||
byte[] rawHmac = mac.doFinal(data.getBytes());
|
||||
|
||||
// base64-encode the hmac
|
||||
return Base64.encodeBase64String(rawHmac);
|
||||
|
||||
} catch (InvalidKeyException ex) {
|
||||
throw new AuthenticationException("Failed to generate HMAC: " + ex.getMessage(), ex);
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
throw new AuthenticationException(HMAC_SHA1_ALGORITHM +
|
||||
" algorithm is not supported", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the canonicalized AMZ headers.
|
||||
*
|
||||
* @param headers
|
||||
* The list of request headers.
|
||||
* @return The canonicalized AMZ headers.
|
||||
*/
|
||||
private static String getCanonicalizedAmzHeaders(final Header[] headers) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Pattern spacePattern = Pattern.compile("\\s+");
|
||||
|
||||
// Create a lexographically sorted list of headers that begin with x-amz
|
||||
SortedMap<String, String> amzHeaders = new TreeMap<String, String>();
|
||||
for (Header header : headers) {
|
||||
String name = header.getName().toLowerCase();
|
||||
|
||||
if (name.startsWith("x-amz-")) {
|
||||
String value = "";
|
||||
|
||||
if (amzHeaders.containsKey(name))
|
||||
value = amzHeaders.get(name) + "," + header.getValue();
|
||||
else
|
||||
value = header.getValue();
|
||||
|
||||
// All newlines and multiple spaces must be replaced with a
|
||||
// single space character.
|
||||
Matcher m = spacePattern.matcher(value);
|
||||
value = m.replaceAll(" ");
|
||||
|
||||
amzHeaders.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Concatenate all AMZ headers
|
||||
for (Entry<String, String> entry : amzHeaders.entrySet()) {
|
||||
sb.append(entry.getKey()).append(':').append(entry.getValue()).append("\n");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the canonicalized resource.
|
||||
*
|
||||
* @param uri
|
||||
* The resource uri
|
||||
* @param hostName
|
||||
* the host name
|
||||
* @return The canonicalized resource.
|
||||
*/
|
||||
private static String getCanonicalizedResource(String uri, String hostName) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// Append the bucket if there is one
|
||||
if (hostName != null) {
|
||||
// If the host name contains a port number remove it
|
||||
if (hostName.contains(":"))
|
||||
hostName = hostName.substring(0, hostName.indexOf(":"));
|
||||
|
||||
// Now extract the bucket if there is one
|
||||
if (hostName.endsWith(".s3.amazonaws.com")) {
|
||||
String bucketName = hostName.substring(0, hostName.length() - 17);
|
||||
sb.append("/" + bucketName);
|
||||
}
|
||||
}
|
||||
|
||||
int queryIdx = uri.indexOf("?");
|
||||
|
||||
// Append the resource path
|
||||
if (queryIdx >= 0)
|
||||
sb.append(uri.substring(0, queryIdx));
|
||||
else
|
||||
sb.append(uri.substring(0, uri.length()));
|
||||
|
||||
// Append the AWS sub-resource
|
||||
if (queryIdx >= 0) {
|
||||
String query = uri.substring(queryIdx - 1, uri.length());
|
||||
|
||||
if (query.contains("?acl"))
|
||||
sb.append("?acl");
|
||||
else if (query.contains("?location"))
|
||||
sb.append("?location");
|
||||
else if (query.contains("?logging"))
|
||||
sb.append("?logging");
|
||||
else if (query.contains("?torrent"))
|
||||
sb.append("?torrent");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getParameter(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSchemeName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isConnectionBased() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void processChallenge(final Header header) throws MalformedChallengeException {
|
||||
// Nothing to do here
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.contrib.auth;
|
||||
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthSchemeFactory;
|
||||
import org.apache.http.params.HttpParams;
|
||||
|
||||
/**
|
||||
* {@link AuthSchemeFactory} implementation that creates and initializes
|
||||
* {@link AWSScheme} instances.
|
||||
*/
|
||||
public class AWSSchemeFactory implements AuthSchemeFactory {
|
||||
|
||||
public AuthScheme newInstance(final HttpParams params) {
|
||||
return new AWSScheme();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.http.contrib.auth;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.impl.auth.SpnegoTokenGenerator;
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1InputStream;
|
||||
import org.bouncycastle.asn1.ASN1Object;
|
||||
import org.bouncycastle.asn1.ASN1OutputStream;
|
||||
import org.bouncycastle.asn1.DERObjectIdentifier;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.DERTaggedObject;
|
||||
import org.bouncycastle.asn1.util.ASN1Dump;
|
||||
|
||||
/**
|
||||
* Takes Kerberos ticket and wraps into a SPNEGO token. Leaving some optional fields out.
|
||||
*/
|
||||
public class BouncySpnegoTokenGenerator implements SpnegoTokenGenerator {
|
||||
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
private final DERObjectIdentifier spnegoOid;
|
||||
private final DERObjectIdentifier kerbOid;
|
||||
|
||||
public BouncySpnegoTokenGenerator() {
|
||||
super();
|
||||
this.spnegoOid = new DERObjectIdentifier("1.3.6.1.5.5.2");
|
||||
this.kerbOid = new DERObjectIdentifier("1.2.840.113554.1.2.2");
|
||||
}
|
||||
|
||||
public byte [] generateSpnegoDERObject(byte [] kerbTicket) throws IOException {
|
||||
DEROctetString ourKerberosTicket = new DEROctetString(kerbTicket);
|
||||
|
||||
DERSequence kerbOidSeq = new DERSequence(kerbOid);
|
||||
DERTaggedObject tagged0 = new DERTaggedObject(0, kerbOidSeq);
|
||||
DERTaggedObject tagged2 = new DERTaggedObject(2, ourKerberosTicket);
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
v.add(tagged0);
|
||||
v.add(tagged2);
|
||||
DERSequence seq = new DERSequence(v);
|
||||
DERTaggedObject taggedSpnego = new DERTaggedObject(0, seq);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ASN1OutputStream asn1Out = new ASN1OutputStream(out);
|
||||
|
||||
ASN1Object spnegoOIDASN1 = (ASN1Object) spnegoOid.toASN1Object();
|
||||
ASN1Object taggedSpnegoASN1 = (ASN1Object) taggedSpnego.toASN1Object();
|
||||
|
||||
int length = spnegoOIDASN1.getDEREncoded().length + taggedSpnegoASN1.getDEREncoded().length;
|
||||
byte [] lenBytes = writeLength(length);
|
||||
byte[] appWrap = new byte[lenBytes.length + 1];
|
||||
|
||||
appWrap[0] = 0x60;
|
||||
for(int i=1; i < appWrap.length; i++){
|
||||
appWrap[i] = lenBytes[i-1];
|
||||
}
|
||||
|
||||
asn1Out.write(appWrap);
|
||||
asn1Out.writeObject(spnegoOid.toASN1Object());
|
||||
asn1Out.writeObject(taggedSpnego.toASN1Object());
|
||||
|
||||
byte[] app = out.toByteArray();
|
||||
ASN1InputStream in = new ASN1InputStream(app);
|
||||
|
||||
if (log.isDebugEnabled() ){
|
||||
int skip = 12;
|
||||
byte [] manipBytes = new byte[app.length - skip];
|
||||
for(int i=skip; i < app.length; i++){
|
||||
manipBytes[i-skip] = app[i];
|
||||
}
|
||||
ASN1InputStream ourSpnego = new ASN1InputStream( manipBytes );
|
||||
log.debug(ASN1Dump.dumpAsString(ourSpnego.readObject()));
|
||||
}
|
||||
|
||||
return in.readObject().getDEREncoded();
|
||||
}
|
||||
|
||||
private byte [] writeLength(int length) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
if (length > 127) {
|
||||
int size = 1;
|
||||
int val = length;
|
||||
|
||||
while ((val >>>= 8) != 0) {
|
||||
size++;
|
||||
}
|
||||
|
||||
out.write((byte) (size | 0x80));
|
||||
|
||||
for (int i = (size - 1) * 8; i >= 0; i -= 8) {
|
||||
out.write((byte) (length >> i));
|
||||
}
|
||||
} else {
|
||||
out.write((byte) length);
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue