AuthenticateAsClient: System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream - c#-2.0

Due to Heartbleed, our Gateway Server was updated and this problem presented itself.
Due to POODLE, SSLv3 is no longer supported.
Note, the problem is only present on Win7+ boxes; WinXP boxes work without issue (same code, different OS = problem); granted WinXP is no longer a valid OS, just wanted to make note of functionality.
Client application (.NET 2.0) sits on a Windows 7 (or 8) box. Server runs within a DMZ behind a Gateway Server. Just to note, I found that this problem is no longer present on .NET 4.0+ - however due to legacy code, I do not have the luxury of updating.
Gateway Server is a pass through box on which Apache HTTP Server with SSL run. Its location is outside the DMZ, and it is used to access the Server which is inside the DMZ. Versions of software running on the Gateway server are Apache/2.2.25 (Win32), mod_jk/1.2.39, mod_ssl/2.2.25, OpenSSL/1.0.1g
Here is the code used on the Client application (with an exorbitant amount of logging added) ... note, 'serverName' typically contains a value such as "https://some.url.com"
private bool ConnectAndAuthenicate(string serverName, out TcpClient client, out SslStream sslStream)
{
client = null;
sslStream = null;
try
{
client = new TcpClient(serverName, 443); // Create a TCP/IP client; ctor attempts connection
Log("ConnectAndAuthenicate: Client CONNECTED"));
sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null);
Log("ConnectAndAuthenicate: SSL Stream CREATED"));
}
catch (Exception x)
{
Log("ConnectAndAuthenicate: EXCEPTION >> CONNECTING to server: {0}", x.ToString()));
if (x is SocketException)
{
SocketException s = x as SocketException;
Log("ConnectAndAuthenicate: EXCEPTION >> CONNECTING to server: Socket.ErrorCode: {0}", s.ErrorCode));
}
if (client != null) { client.Close(); client = null; }
if (sslStream != null) { sslStream.Close(); sslStream = null; }
}
if (sslStream == null) return false;
try
{
sslStream.ReadTimeout = 10000; // wait 10 seconds for a response ...
Log("ConnectAndAuthenicate: AuthenticateAsClient CALLED ({0})", serverName));
sslStream.AuthenticateAsClient(serverName);
Log("ConnectAndAuthenicate: AuthenticateAsClient COMPLETED SUCCESSFULLY"));
return true;
}
catch (Exception x)
{
Log("ConnectAndAuthenicate: EXCEPTION >> AuthenticateAsClient: {0}", x.ToString()));
client.Close(); client = null;
sslStream.Close(); sslStream = null;
}
return false;
}
Note - answers posted pertaining to ServicePointManager have absolutely no effect on the outcome of this application.
Every time that AuthenicateAsClient() is called when application is run on Win 7+ box, the exception occurs - if application is run on WinXP box, code works properly without exceptions.
Any ideas for solutions are very welcome.

Following the trail of setting the ServicePointManager.SecurityProtocol static ctor with a SecurityProtocolType, I found mention of another enum called SslPolicy -- further research found that AuthenicateAsClient has an overload that takes SslPolicy as an argument.
Changing this line in the above code fixed this problem:
sslStream.AuthenticateAsClient(serverName, null, SslPolicy.Tls, false);

Related

How To Consume Stream HTTP Response In Java?

I'm having trouble trying to consume the Response of an HTTP Endpoint which Streams real-time events continously. It's actually one of Docker's endpoints: https://docs.docker.com/engine/api/v1.40/#operation/SystemEvents
I am using Apache HTTP Client 4.5.5 and it just halts indefinitely when I try to consume the content InputStream:
HttpEntity entity = resp.getEntity();
EntityUtils.consume(entity);//it just hangs here.
//Even if I don't call this method, Apache calls it automatically
//after running all my ResponseHandlers
Apparently, it can be done by using JDK's raw URL: Stream a HTTP response in Java
But I cannot do that since local Docker communicates over a Unix Socket which I only managed to configure in Apache's HTTP Client with a 3rd party library for Unix Sockets in Java.
If there is a smarter HTTP Client library which I could switch to, that would also be an option.
Any ideas would be greatly appreciated. Thank you!
I managed to solve this issue by generating an infinite java.util.stream.Stream of JsonObject from the response InputStream (I know the json reading part is not the most elegant solution but there is no better way with that API and also, Docker doesn't send any separator between the jsons).
final InputStream content = response.getEntity().getContent();
final Stream<JsonObject> stream = Stream.generate(
() -> {
JsonObject read = null;
try {
final byte[] tmp = new byte[4096];
while (content.read(tmp) != -1) {
try {
final JsonReader reader = Json.createReader(
new ByteArrayInputStream(tmp)
);
read = reader.readObject();
break;
} catch (final Exception exception) {
//Couldn't parse byte[] to Json,
//try to read more bytes.
}
}
} catch (final IOException ex) {
throw new IllegalStateException(
"IOException when reading streamed JsonObjects!"
);
}
return read;
}
).onClose(
() -> {
try {
((CloseableHttpResponse) response).close();
} catch (final IOException ex) {
//There is a bug in Apache HTTPClient, when closing
//an infinite InputStream: IOException is thrown
//because the client still tries to read the remainder
// of the closed Stream. We should ignore this case.
}
}
);
return stream;

ActiveMQ test connection

I am trying to test ActiveMQ connection and return a value. it crashes on line:
httpResponse = client.execute(theHttpGet);
It is not my code I am trying to debug it. Can anyone help me to understand why the code is using HttpGet?
public ActivemqBrokerInfo(String serverAddress, int port, String apiUrl, int timeout) {
// Default Activemq location
this.serverAddress = String.format("http://%s:%s/%s", serverAddress, port, apiUrl);
int timeoutInMs = timeout;
HttpClientBuilder builder = HttpClientBuilder.create();
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeoutInMs).build();
builder.setDefaultRequestConfig(requestConfig);
client = builder.build();
}
public ActivemqBrokerInfo(String serverAddress) {
this(serverAddress, DEFAULT_PORT, DEFAULT_API_URL, DEFAULT_TIMEOUT);
}
#Override
public boolean testConnection() {
HttpGet theHttpGet = new HttpGet(serverAddress);
theHttpGet.addHeader("test-header-name", "test-header-value");
HttpResponse httpResponse = null;
try{
httpResponse = client.execute(theHttpGet);// Code is crashing on this line
} catch (IOException ex){
LOGGER.error("Broker down: ", ex);
}
return httpResponse != null;
}
When ActiveMQ runs is normally starts an embedded web server. This web server is used to host the web admin console as well as the Jolokia endpoint which acts as an HTTP facade in front of the broker's MBeans. In other words, any client can send HTTP requests to specially formed URLs on the broker to get results from the underlying management beans. This is exactly what your bit of code appears to be doing. It appears to be sending an HTTP request to the Jolokia endpoint (i.e. api/jolokia) in order to determine if the broker is alive or not.
Based on the information provided it is impossible to determine why testConnection() is not returning successfully since you've included no information about the configuration or state of the broker.
I recommend you add additional logging to see what may be happening and also catch Exception rather than just IOException.

No errors are being raised when unsuccessfully writing to Azure service bus

When writing a message to the Azure Service Bus (using Microsoft.Azure.ServiceBus standard library, not the .Net Framework version) it works fine. However, when switching networks to a network that blocks that traffic and running it again I would expect an error being raised by SendAsync yet no error is thrown, therefor the function considers the send successful even though it is not.
Am I missing some logic to make sure that errors do get raised and trapped, it seems to be inline with all the examples I have seen.
I have tried this possible solution ..
Trouble catching exception on Azure Service Bus SendAsync method
.ContinueWith(t =>
{
Console.WriteLine(t.Status + "," + t.IsFaulted + "," + t.Exception.InnerException);
}, TaskContinuationOptions.OnlyOnFaulted);
.. and at no point does ContinueWith get hit.
[HttpPost]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<Boolean> Post(Contract<T> contract)
{
Task.Run(() => SendMessage(contract));
// Other stuff
}
private async Task<ActionResult<Boolean>> SendMessage(Contract<T> contract)
{
JObject json = JObject.FromObject(contract);
Message message = new Message();
message.MessageId = Guid.NewGuid().ToString();
message.ContentType = ObjectType;
message.PartitionKey = ObjectType;
message.Body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(contract));
foreach (KeyValuePair<String, String> route in DataRouting)
{
JToken jToken = json.SelectToken(route.Value);
if (jToken != null)
{
message.UserProperties[route.Key] = jToken.Value<String>();
}
else
{
String routeError = $"Could not find routing information in request for: {route.Key} in {route.Value}";
Logger.LogError(routeError);
return new UnprocessableEntityObjectResult(routeError);
}
}
// Send the message
try
{
await topicClient.SendAsync(message);
}
catch(Exception ex)
{
return new UnprocessableEntityObjectResult($"'Could not transmit message to service bus - {ex.Message}'");
}
return new OkObjectResult(true);
}
I expect that the error trap would be hit if the SendAsync fails to send the message. However it essentially fire and forgets, the message send is blocked by the firewall but is never reported to the caller by throwing an error.
Ok, found the answer, but I will leave this out there in case anyone else does this to themselves. It was down to my general muppetry when putting the MVC Controller together. Set async on the Post action and configure the await on the send. Obvious really but I missed it.
public virtual async Task<ActionResult<Boolean>> Post(Contract<T> contract){}
...
// Send the message
try
{
await topicClient.SendAsync(message).ConfigureAwait(false);
return new OkObjectResult(true); // Success if we got here
}
catch(Exception ex)
{
return new UnprocessableEntityObjectResult($"'Could not transmit message to service bus - {ex.Message}'");
}

Why this f# echo server can't be connected by many clients?

I write this echo server:
let listener=new TcpListener(IPAddress.Parse("127.0.0.1"),2000)
let rec loop (client : TcpClient,sr : StreamReader, sw : StreamWriter) =
async {
let line=sr.ReadLine()
sw.WriteLine(line)
if line="quit" then
client.Close()
else
return! loop(client,sr,sw)
}
let private startLoop (listener:TcpListener) =
while true do
let client = listener.AcceptTcpClient()
let stream = client.GetStream()
let sr = new StreamReader(stream)
let sw = new StreamWriter(stream)
sw.AutoFlush <- true
sw.WriteLine("welcome")
Async.Start(loop (client,sr,sw))
[<EntryPoint>]
let main argv =
listener.Start()
startLoop(listener)
0
when I open one or two telnet window to test it,it works fine
but when I write this test program to test it:
static void Main(string[] args)
{
for (int a = 0; a < 5; a++)
{
var client = new TcpClient("localhost", 2000);
Console.WriteLine(client.Connected);
client.close();
}
}
the test program return one or two true,but the server raise an exception:
System.Net.Sockets.SocketException:An existing connection was forcibly closed by the remote host
in line 12:let line=sr.ReadLine()
and client raise the exception:System.Net.Sockets.SocketException:Because the target computer actively refused, unable to connect
at line 16:var client = new TcpClient("localhost", 2000);
I don't know why,please help me
Your problem is that the client opens a connection and then immediately closes it.
The server however expects a "quit" message from the client before it will terminate the connection. So the server sends a "welcome" to the client, then enters the loop. Inside the loop, sr.ReadLine() is called, which waits for the client to send something over the wire.
The client never sends anything. It closes the connection. Therefore, the server's call to ReadLine aborts with the a SocketException (forcibly closed...). And you do not handle this exception, so the server dies.
Then the client tries to connect once again, with no server listening anymore. The client can't connect and you see another SocketException (actively refused...).
You should guard your server code against clients that disconnect without saying "quit" first.

BlackBerry ConnectionFactory timeout

I upgraded an existing application and in the new version I require OS 5 - one of the reasons was that I wanted to use ConnectionFactory for communicating via HTTP/HTTPS with our server without having to add all the URL parameters for using BES, BIS, Direct TCP, Wifi and so on.
The ConnectionFactory is now configured to choose the best way to connect to our services via preferred types.
My connection code looks like this:
ConnectionFactory connectionFactory = new ConnectionFactory();
BisBOptions bisOptions = new BisBOptions(BIS_SECRET);
connectionFactory.setTransportTypeOptions(TransportInfo.TRANSPORT_BIS_B, bisOptions);
connectionFactory.setConnectionMode(ConnectionFactory.ACCESS_READ_WRITE);
connectionFactory.setEndToEndDesired(true);
connectionFactory.setPreferredTransportTypes(new int[] { TransportInfo.TRANSPORT_BIS_B, TransportInfo.TRANSPORT_MDS,
TransportInfo.TRANSPORT_TCP_WIFI, TransportInfo.TRANSPORT_TCP_CELLULAR });
ConnectionDescriptor connectionDescriptor = connectionFactory.getConnection("https://myserver.com/serviceurl");
try {
HttpConnection con = (HttpConnection) connectionDescriptor.getConnection();
byte[] bytes = parameter.toString().getBytes(UTF_8);
con.setRequestProperty(CONTENT_LENGTH, String.valueOf(bytes.length));
os = con.openOutputStream();
os.write(bytes);
os.flush();
int responseCode = con.getResponseCode();
if (responseCode == 401) {
throw new InvalidCredentialsException("Invalid credentials");
} else if (responseCode != 200 && responseCode != 500) {
EventLogger.logEvent(RTSID, ("Response code " + responseCode + " " + con
.getResponseMessage()).getBytes(), EventLogger.ERROR);
EventLogger.logEvent(RTSID, bytes, EventLogger.ERROR);
throw new IOException("Invalid request");
}
is = con.openInputStream();
if (is != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c = 0;
try {
c = is.read();
} catch (Exception ex) {
c = -1;
}
while (c >= 0) {
baos.write(c);
try {
c = is.read();
} catch (Exception ex) {
c = -1;
}
}
String response = new String(baos.toByteArray(), UTF_8);
try {
JSONObject jsonObject;
if (response.startsWith("[")) {
jsonObject = new JSONObject();
jsonObject.put(ARRAY, new JSONArray(response));
} else {
jsonObject = new JSONObject(response);
}
if (responseCode == 500) {
throw new Exception(jsonObject.getString("message"));
}
return jsonObject;
} catch (JSONException e) {
EventLogger.logEvent(RTSID, ("Exception occured: " + e.toString()).getBytes(),
EventLogger.ERROR);
}
}
} finally {
if (is != null) {
try {
is.close();
} catch (Exception e) {
}
}
if (os != null) {
try {
os.close();
} catch (Exception e) {
}
}
if (con != null) {
try {
con.close();
} catch (Exception e) {
}
}
}
My problem is that this works not as well as when I added the connection parameters to my URL manually. I get errors in the server logs looking like the clients close the connection after some kind of timeout.
Here are some log examples:
93.186.30.120 - - [28/Jun/2012:15:50:08 +0200] "POST /service/methodX HTTP/1.1" 400 145 "-" "myapp VendorID/301" 10012567
93.186.22.118 - - [28/Jun/2012:16:30:56 +0200] "POST /service/methodY HTTP/1.1" 400 145 "-" "myapp VendorID/137" 10012435
74.82.68.35 - - [28/Jun/2012:16:53:23 +0200] "POST /service/methodZ HTTP/1.1" 400 145 "-" "myapp BlackBerry9650/6.0.0.524 VendorID/105" 10012644
The IP Adresses are from RIM Networks - so these are Connections comming from BIS
Those connections got status code 400 (Bad Request) from the server
The large numbers at the end of the line (e.g. 10012644) show the time the request was processed on the server in microseconds: 10012644 = about 10 seconds
Do the RIM servers add a connection timeout of 10 seconds? That seems fairly short!
The problem is difficult to reproduce - has anybody experienced something like that before?
I found the reason. Problem was caused by default configuration of Apache module mod_reqtimeout:
<IfModule reqtimeout_module>
# mod_reqtimeout limits the time waiting on the client to prevent an
# attacker from causing a denial of service by opening many connections
# but not sending requests. This file tries to give a sensible default
# configuration, but it may be necessary to tune the timeout values to
# the actual situation. Note that it is also possible to configure
# mod_reqtimeout per virtual host.
# Wait max 20 seconds for the first byte of the request line+headers
# From then, require a minimum data rate of 500 bytes/s, but don't
# wait longer than 40 seconds in total.
# Note: Lower timeouts may make sense on non-ssl virtual hosts but can
# cause problem with ssl enabled virtual hosts: This timeout includes
# the time a browser may need to fetch the CRL for the certificate. If
# the CRL server is not reachable, it may take more than 10 seconds
# until the browser gives up.
RequestReadTimeout header=20-40,minrate=500
# Wait max 10 seconds for the first byte of the request body (if any)
# From then, require a minimum data rate of 500 bytes/s
RequestReadTimeout body=10,minrate=500
</IfModule>
I guess BlackBerry clients wer hit harder because sending request body via RIM BIS infrastructure takes longer.
Set the value to 100 seconds and monitoring if clients are still affected.

Resources