org.bouncycastle.est.jcajce.DefaultESTClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcpkix-fips Show documentation
Show all versions of bcpkix-fips Show documentation
The Bouncy Castle Java APIs for CMS, PKCS, EAC, TSP, CMP, CRMF, OCSP, and certificate generation. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified.
package org.bouncycastle.est.jcajce;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.bouncycastle.est.ESTClient;
import org.bouncycastle.est.ESTClientSourceProvider;
import org.bouncycastle.est.ESTException;
import org.bouncycastle.est.ESTRequest;
import org.bouncycastle.est.ESTRequestBuilder;
import org.bouncycastle.est.ESTResponse;
import org.bouncycastle.est.Source;
import org.bouncycastle.util.Properties;
import org.bouncycastle.util.Strings;
class DefaultESTClient
implements ESTClient
{
private static final Charset utf8 = Charset.forName("UTF-8");
private static byte[] CRLF = new byte[]{'\r', '\n'};
private final ESTClientSourceProvider sslSocketProvider;
public DefaultESTClient(ESTClientSourceProvider sslSocketProvider)
{
this.sslSocketProvider = sslSocketProvider;
}
private static void writeLine(OutputStream os, String s)
throws IOException
{
os.write(s.getBytes());
os.write(CRLF);
}
public ESTResponse doRequest(ESTRequest req)
throws IOException
{
ESTResponse resp = null;
ESTRequest r = req;
int rcCount = 15;
do
{
resp = performRequest(r);
r = redirectURL(resp);
}
while (r != null && --rcCount > 0); // Follow redirects.
if (rcCount == 0)
{
throw new ESTException("Too many redirects..");
}
return resp;
}
protected ESTRequest redirectURL(ESTResponse response)
throws IOException
{
ESTRequest redirectingRequest = null;
if (response.getStatusCode() >= 300 && response.getStatusCode() <= 399)
{
switch (response.getStatusCode())
{
case 301:
case 302:
case 303:
case 306:
case 307:
String loc = response.getHeader("Location");
if ("".equals(loc))
{
throw new ESTException("Redirect status type: " + response.getStatusCode() + " but no location header");
}
ESTRequestBuilder requestBuilder = new ESTRequestBuilder(response.getOriginalRequest());
if (loc.startsWith("http"))
{
redirectingRequest = requestBuilder.withURL(new URL(loc)).build();
}
else
{
URL u = response.getOriginalRequest().getURL();
redirectingRequest = requestBuilder.withURL(new URL(u.getProtocol(), u.getHost(), u.getPort(), loc)).build();
}
break;
default:
throw new ESTException("Client does not handle http status code: " + response.getStatusCode());
}
}
if (redirectingRequest != null)
{
response.close(); // Close original request.
}
return redirectingRequest;
}
public ESTResponse performRequest(ESTRequest c)
throws IOException
{
ESTResponse res = null;
Source socketSource = null;
try
{
socketSource = sslSocketProvider.makeSource(c.getURL().getHost(), c.getURL().getPort());
if (c.getListener() != null)
{
c = c.getListener().onConnection(socketSource, c);
}
// socketSource = new SSLSocketSource((SSLSocket)sock);
OutputStream os = null;
Set opts = asKeySet("org.bouncycastle.debug.est");
if (opts.contains("output") ||
opts.contains("all"))
{
os = new PrintingOutputStream(socketSource.getOutputStream());
}
else
{
os = socketSource.getOutputStream();
}
String req = c.getURL().getPath() + ((c.getURL().getQuery() != null) ? c.getURL().getQuery() : "");
ESTRequestBuilder rb = new ESTRequestBuilder(c);
Map headers = c.getHeaders();
if (!headers.containsKey("Connection"))
{
rb.addHeader("Connection", "close" );
}
// Replace host header.
URL u = c.getURL();
if (u.getPort() > -1)
{
rb.setHeader("Host", String.format("%s:%d", u.getHost(), u.getPort()));
}
else
{
rb.setHeader("Host", u.getHost());
}
ESTRequest rc = rb.build();
writeLine(os, rc.getMethod() + " " + req + " HTTP/1.1");
for (Iterator it = rc.getHeaders().entrySet().iterator(); it.hasNext();)
{
Map.Entry ent = (Map.Entry)it.next();
String[] vs = (String[])ent.getValue();
for (int i = 0; i != vs.length; i++)
{
writeLine(os, ent.getKey() + ": " + vs[i]);
}
}
os.write(CRLF);
os.flush();
rc.writeData(os);
os.flush();
if (rc.getHijacker() != null)
{
res = rc.getHijacker().hijack(rc, socketSource);
return res;
}
else
{
res = new ESTResponse(rc, socketSource);
}
return res;
}
finally
{
// Close only if response not generated.
if (socketSource != null && res == null)
{
socketSource.close();
}
}
}
private class PrintingOutputStream
extends OutputStream
{
private final OutputStream tgt;
public PrintingOutputStream(OutputStream tgt)
{
this.tgt = tgt;
}
public void write(int b)
throws IOException
{
System.out.print(String.valueOf((char)b));
tgt.write(b);
}
}
static Set asKeySet(String propertyName)
{
Set set = new HashSet();
String p = fetchProperty(propertyName);
if (p != null)
{
StringTokenizer sTok = new StringTokenizer(p, ",");
while (sTok.hasMoreElements())
{
set.add(Strings.toLowerCase(sTok.nextToken()).trim());
}
}
return Collections.unmodifiableSet(set);
}
private static String fetchProperty(final String propertyName)
{
return (String)AccessController.doPrivileged(new PrivilegedAction()
{
public Object run()
{
return System.getProperty(propertyName);
}
});
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy