Odd socket behaviour under Mono 3.2.8 on Debian - vb.net

I'm writing a VB.Net app in VS2015 which connects to a socket and listens for data. It works perfectly on Windows but when I try to run it under Mono 3.2.8 I get an unusual behaviour.
Here is a simplified version of my code. This works on Windows:
Module Module1
Sub Main()
' Declare client socket and client stream to get data from the dongle etc
Dim clientSocket As New TcpClient()
Dim clientStream As NetworkStream
' Connect to socket
clientSocket.ExclusiveAddressUse = False
clientSocket.LingerState.LingerTime = 0
' Try to connect to socket
Try
clientSocket.Connect("127.0.0.1", 30003)
Catch ex As Exception
' write error
Console.WriteLine("Exception: " & ex.ToString())
End Try
' Tie server stream to socket
clientStream = clientSocket.GetStream()
End Sub
End Module
The error message thrown is:
Unhandled Exception:
System.InvalidOperationException: Bind has already been called for this socket
at System.Net.Sockets.Socket.set_ExclusiveAddressUse (Boolean value) [0x00000] in :0
at System.Net.Sockets.TcpClient.set_ExclusiveAddressUse (Boolean value) [0x00000] in :0
at ConsoleApplication1.Module1.Main () [0x00000] in :0
[ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: Bind has already been called for this socket
at System.Net.Sockets.Socket.set_ExclusiveAddressUse (Boolean value) [0x00000] in :0
at System.Net.Sockets.TcpClient.set_ExclusiveAddressUse (Boolean value) [0x00000] in :0
at ConsoleApplication1.Module1.Main () [0x00000] in :0
As I'm setting clientSocket.ExclusiveAddressUse = False before I specify the IP address and port I can't see why it's failing.
Looking around on the web I can see mentions of this as a bug back in 2010 but nothing more recent. I've searched the release notes of all releases after 3.2.8 but there is no mention so it looks like this is still a bug ?
If it is, is there a work around ?

Related

Get WebException on compatible S3 storage

I develop an application that connects with a compatible S3 server located in an internal network. For that reason, the server where this app is going to run does not have internet connectivity.
I am using the amazon web service sdk (AWSSDK.S3) to connect with the server and it provides all the necessary functionality.
When I try to connect with the server, it seems that the SDK tries to connect with a real amazon webservice server and it fails.
This is the code I am trying
Dim config As AmazonS3Config = New AmazonS3Config With {
.ForcePathStyle = True,
.ServiceURL = cloudEndpoint,
.RegionEndpoint = Amazon.RegionEndpoint.GetBySystemName(region)
}
config.Validate()
s3Client = New AmazonS3Client(cloudAccessKey, cloudSecretKey, config)
Dim listBuckets As ListBucketsResponse = s3Client.ListBuckets()
The S3Client is generated correctly but when I tried to get the buckets, I get the following exception:
Error creating s3. Exception: Amazon.Runtime.AmazonServiceException: A WebException with status ConnectFailure was thrown. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond ** 52.216.143.230:80 **
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.GetResponse()
at Amazon.Runtime.Internal.HttpRequest.GetResponse()
at Amazon.Runtime.Internal.HttpHandler`1.InvokeSync(IExecutionContext executionContext)
at Amazon.Runtime.Internal.RedirectHandler.InvokeSync(IExecutionContext executionContext)
at Amazon.Runtime.Internal.Unmarshaller.InvokeSync(IExecutionContext executionContext)
at Amazon.S3.Internal.AmazonS3ResponseHandler.InvokeSync(IExecutionContext executionContext)
at Amazon.Runtime.Internal.ErrorHandler.InvokeSync(IExecutionContext executionContext)
--- End of inner exception stack trace ---
at TestS3.S3CDM..ctor(String endpoint, String accessKey, String secretKey, String region, String bucketName)
at TestS3.Form1.btn_CreateConnector_Click(Object sender, EventArgs e)
The server (52.216.143.230:80) that appears in the exception is not my s3 server, searching I find that it´s an amazon server.
Is it necessary connectivity to internet to use this SDK? Or I forget any additional configuration?
Thank you in advance.

Access self signed X509certificates in XamarinForms for mqtt TLS connection to a Mosquitto broker

I desire to TLS secure with a self signed x509certificate a number of existing XamarinForms apps that connect to a mosquitto mqtt broker using the M2MqttDotnetCore client.
To that end I have created a simple sample XamarinForms pub/sub chat app to learn how to secure an XamarinForms mqtt client application that can be sound in this GitHub repository. jhalbrecht/XamarinFormsMqttSample
I have samples in Mosquitto_pub, python and a .net console app that accomplish this goal of successfully connecting to a mosquitto broker over port 8883 with TLS and a self signed certificate. The XamarinForms UWP app also works unsecured and secured. I'm having trouble getting the Android app to work with TLS on port 8883, The Android app does work unsecured on port 1883. This is the runtime log from Visual Studio 2017
[0:] M2Mqtt.Exceptions.MqttConnectionException: Exception connecting to the broker ---> System.AggregateException: One or more errors occurred. ---> System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. ---> Mono.Btls.MonoBtlsException: Ssl error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED
at /Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/external/boringssl/ssl/handshake_client.c:1132
at Mono.Btls.MonoBtlsContext.ProcessHandshake () [0x00038] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
at Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake (Mono.Net.Security.AsyncOperationStatus status) [0x0003e] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
at (wrapper remoting-invoke-with-check) Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake(Mono.Net.Security.AsyncOperationStatus)
at Mono.Net.Security.AsyncHandshakeRequest.Run (Mono.Net.Security.AsyncOperationStatus status) [0x00006] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
at Mono.Net.Security.AsyncProtocolRequest+<ProcessOperation>d__24.MoveNext () [0x000ff] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
--- End of stack trace from previous location where exception was thrown ---
at Mono.Net.Security.AsyncProtocolRequest+<StartOperation>d__23.MoveNext () [0x0008b] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
--- End of inner exception stack trace ---
at Mono.Net.Security.MobileAuthenticatedStream+<ProcessAuthentication>d__47.MoveNext () [0x00254] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00011] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.Wait (System.Int32 millisecondsTimeout, System.Threading.CancellationToken cancellationToken) [0x00043] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.Wait () [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at M2Mqtt.Net.MqttNetworkChannel.Connect () [0x000a8] in <72fbe921f857483bafbb8b397ec98dd1>:0
at M2Mqtt.MqttClient.Connect (System.String clientId, System.String username, System.String password, System.Boolean willRetain, System.Byte willQosLevel, System.Boolean willFlag, System.String willTopic, System.String willMessage, System.Boolean cleanSession, System.UInt16 keepAlivePeriod) [0x0001e] in <72fbe921f857483bafbb8b397ec98dd1>:0
--- End of inner exception stack trace ---
at M2Mqtt.MqttClient.Connect (System.String clientId, System.String username, System.String password, System.Boolean willRetain, System.Byte willQosLevel, System.Boolean willFlag, System.String willTopic, System.String willMessage, System.Boolean cleanSession, System.UInt16 keepAlivePeriod) [0x00037] in <72fbe921f857483bafbb8b397ec98dd1>:0
at M2Mqtt.MqttClient.Connect (System.String clientId) [0x00000] in <72fbe921f857483bafbb8b397ec98dd1>:0
at MqttDataServices.Services.MqttDataService+<Initialize>d__5.MoveNext () [0x00266] in C:\jstuff\MqttSample\MqttDataServices\Services\MqttDataService.cs:183
The way I am currently loading and accessing the X509certificates is not secure or a best practice. It works. I hope to eventually learn how to access the device ca keystores for each mobile platform. I use the cross-platform plug-in FilePicker to load a cert, base64 encode it, and save it.
FileData fileData = await Plugin.FilePicker.CrossFilePicker.Current.PickFile();
if (fileData == null)
return; // user canceled file picking
string fileName = fileData.FileName;
string content = Convert.ToBase64String(fileData.DataArray, 0, fileData.DataArray.Length,
Base64FormattingOptions.None);
string deviceFileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), fileName);
File.WriteAllText(deviceFileName, content);
I have reached out to a few Xamarin folks via twitter. I have an open issue in my above mentioned repository discussing the problem where #baulig from Microsoft has I believe given me the answer however I don't currently know how to implement it.
I just looked at the certificate validation code and what it does is
essentially
var certStore = KeyStore.GetInstance ("AndroidCAStore");
certStore.Load(null);
This is the entry point:
https://github.com/mono/mono/blob/master/mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs,
it calls this code
https://github.com/mono/mono/blob/master/mcs/class/System/System/AndroidPlatform.cs#L101
which then calls into xamarin-android code here:
https://github.com/xamarin/xamarin-android/blob/master/src/Mono.Android/Android.Runtime/AndroidEnvironment.cs
The KeyStore should be this class:
https://developer.xamarin.com/api/type/Java.Security.KeyStore/.
So you should be able to do this via Java.Security.KeyStore.
What permissions are necessary to grant in AndroidManifest.xml?
What terms might I research to properly access the platform ca keystores?
Additions after initial posting
February 27, 2019 (MST) 2:51 PM
Added certs and mqtt client creation from MqttDataService.cs
X509Certificate caCert = X509Certificate.CreateFromCertFile(Path.Combine(filesDirectoryBasePath, "ca.crt"));
string thePfxPathOnDevice = Path.Combine(filesDirectoryBasePath, "xamarinclient.pfx");
string theBase64EncodedPfx = File.ReadAllText(thePfxPathOnDevice);
byte[] certificate = Convert.FromBase64String(theBase64EncodedPfx);
X509Certificate2 clientCert = new X509Certificate2(certificate, "xamarin");
_client = new MqttClient(
GetHostName(_xpdSetting.MqttBrokerAddress),
Int32.Parse(_xpdSetting.MqttBrokerTlsPort),
_xpdSetting.UseTls,
caCert,
clientCert,
MqttSslProtocols.TLSv1_2
//MyRemoteCertificateValidationCallback
);
Since you are using .Net's/Mono Socket (via M2MqttDotnetCore), just use cert pinning and you only have to handle the RemoteCertificateValidationCallback. Thus no messing with Android's trusted stores, etc...
SslStream Usage on Android:
Note: There are issues with SslStream on Android, object allocations can go crazy... I believe(?) there is an open issue about this. (I had to use Java's SSLSocket a couple times to work around this issue)
Enable Native TLS 1.2+
Using BoringSSL via the Android project build options
Add your cert to the Android's Asset directory:
├── Assets
│   └── sushihangover.cert
This is your cert/.pem file (NOT your KEY!!)
Make sure that this is an ascii file with no unicode BOM header
Via openssl example (just change it to your host and secure port)
echo -n | openssl s_client -connect 10.1.10.250:5001 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
RemoteCertificateValidationCallback Implementation
Note: The following code can be in used in NetStd2.0 or Xamarin.Android
X509Certificate sushihangoverCert; // Class level var
bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors certificateErrors)
{
if (sushihangoverCert == null)
{
// There is no non-async version of OpenAppPackageFileAsync (via Xamarin.Essential) 😡 Why!!!
using (var waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset))
{
Task.Run(async () =>
{
using (var assetStream = await Xamarin.Essentials.FileSystem.OpenAppPackageFileAsync("sushihangover.cert"))
using (var memStream = new MemoryStream())
{
assetStream.CopyTo(memStream);
sushihangoverCert = new X509Certificate(memStream.ToArray());
waitHandle.Set();
}
});
waitHandle.WaitOne();
}
}
return sushihangoverCert.Equals(certificate) ? true : false;
}
SSLStream Usage Example:
Note: This is connecting to a NetCore Web API port using a self-signed cert
using (var tcpClient = new TcpClient("10.1.10.250", 5001))
using (var ssl = new SslStream(tcpClient.GetStream(), false, new RemoteCertificateValidationCallback(CertificateValidation)))
{
ssl.AuthenticateAsClient("10.1.10.250", null, System.Security.Authentication.SslProtocols.Tls12, false);
if (ssl.CanWrite)
{
var send = Encoding.ASCII.GetBytes("GET /api/item HTTP/1.1\r\nhost: 10.1.10.250\r\n\r\n");
await ssl.WriteAsync(send, 0, send.Length);
var buffer = new byte[4096];
var count = await ssl.ReadAsync(buffer, 0, buffer.Length);
Console.WriteLine(Encoding.UTF8.GetString(buffer, 0, count));
}
else
throw new SocketException();
}
Server cert mismatch error:
If your server cert (self-signed or not) does not match the one that you are pinning to, you will receive:
{Mono.Btls.MonoBtlsException: Ssl error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED

Unable to connect WIA Scanner over virtual machine

I have following vb code to connect scanner via WIA in a Windows form application.
Private Function Connect() As Device
Dim WiaDev As Device = Nothing
Dim manager As New DeviceManager()
Try
For Each info As DeviceInfo In manager.DeviceInfos
If info.DeviceID = DeviceID Then
WiaDev = info.Connect()
Return WiaDev
End If
Next
Throw New Exception(ex.Message)
End Try
End Function
It works fine in local. But in virtual machine it throws following exception while executing the line info.Connect(). Exception =>
"Error HRESULT E_FAIL has been returned from a call to a COM component". It will be nice if anybody suggest some solution. Thanks :)
I found solution that , it is necessary to install corresponding scanner driver in both local and virtual machine.

Self hosted cross site connection issue with SignalR and Mono and Owin

I'm about ready to pull my hair out over this problem because all the guides show the same one or two solutions, which seem to be working for everyone but myself.
I'm using SignalR in a Mono application, using Owin. I've set EnableCrossDomain = true in my HubConfiguration. I've set up a simple test page using javascript to connect. The negotiate and ping urls are loading without issue and seem to be replying correctly. However I get a cross domain error on the connect call.
It's definitely using my EnableCrossDomain setting because if I set that to false, negotiate doesn't work.
Here's my Javascript to connect (and yes I'm including the /signalr/hubs script which returns the appropriate javascript):
$.connection.hub.url = 'http://localhost:7001/signalr';
$.connection.hub.logging = true;
$.connection.hub.start()
.done(function () { alert("Now connected!"); })
.fail(function () { alert("Could not Connect!"); });
Also I've tried jQuery.support.cors = true; as well but it doesn't make any difference.
I also tried connecting to a regular PersistantConnection like so, with the same problem, so it doesn't appear to be directly related to hubs:
var connection = $.connection('/raw');
connection.url = 'http://localhost:7001/signalr';
connection.start()
.done(function () { alert("Now connected!"); })
.fail(function () { alert("Could not Connect!"); });
What am I doing wrong here? Why do ping and negotiate work but not connect?
EDIT: Also to make matters weirder, I added some logging and verified that the SignalR CallHandler class is adding the Access-Control-Allow-Origin header for all requests, including the connect request. So it should be working.
EDIT 2: So actually thanks to curl it looks like the server is returning a 500 response code, and since it's not also including the header (this must be happening after the code block I added the logging to), Chrome complains about cross site, when really there's probably an exception being thrown somewhere in the server. Hopefully I'll have this figured out shortly and will post an answer here.
So it actually turned out to have nothing to do with cross site access, and everything to do with Mono incompatibilities.
After I enabled exception logging for SignalR (https://stackoverflow.com/a/16577890/299262) I got the following exception instead of just a blank http 500 error:
System.InvalidOperationException: The connection id is in the incorrect format.
at Microsoft.AspNet.SignalR.PersistentConnection.GetConnectionId (Microsoft.AspNet.SignalR.Hosting.HostContext context, System.String connectionToken) [0x00000] in <filename unknown>:0
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest (Microsoft.AspNet.SignalR.Hosting.HostContext context) [0x00000] in <filename unknown>:0
at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.ProcessRequest (Microsoft.AspNet.SignalR.Hosting.HostContext context) [0x00000] in <filename unknown>:0
at Microsoft.AspNet.SignalR.Owin.CallHandler.Invoke (IDictionary`2 environment) [0x00000] in <filename unknown>:0
at Microsoft.AspNet.SignalR.Owin.Handlers.HubDispatcherHandler.Invoke (IDictionary`2 environment) [0x00000] in <filename unknown>:0
at Microsoft.AspNet.SignalR.Owin.Handlers.PersistentConnectionHandler.Invoke (IDictionary`2 environment) [0x00000] in <filename unknown>:0
at Microsoft.Owin.Diagnostics.ShowExceptionsMiddleware.Invoke (IDictionary`2 environment) [0x00000] in <filename unknown>
That led me to find this ticket on the SignalR repo issues list: https://github.com/SignalR/SignalR/issues/1914
So in the end, the fix was to comment out the following line in HostDependencyResolverExtensions.cs:
resolver.InitializePerformanceCounters(instanceName, hostShutdownToken);

HttpWebRequest crashing outside MonoDevelop

I wrote a method to submit an error-report via HTTP POST. I run OSX-Lion and MonoDevelop. The code works when the application is called from MonoDevelop. When I run the .app it throws an exception:
System.TypeInitializationException: An exception was thrown by the type initializer for System.Net.WebRequest ---> System.DllNotFoundException: libc.dylib
at (wrapper managed-to-native) System.Platform:uname (intptr)
at System.Platform.get_IsMacOS () [0x00000] in <filename unknown>:0
at System.Net.WebRequest..cctor () [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at ch.fangorn.LIF.Access.SubmitCrash.Submit (Int32 projectId) [0x00000] in <filename unknown>:0
At the moment I call the Submit method directly not via a catch. Since it works when a debugger is attached I'm stranded. What I so far tried:
Build a mono application bundle (Create mac installer)
Build everything with Platform target x86
The beta version of Mono and MonoDevelop
The code that IMO causes the crash.
HttpWebRequest hwr = WebRequest.Create(turi) as HttpWebRequest;
string authInfo = user + ":" + password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
hwr.Headers["Authorization"] = "Basic " + authInfo;
hwr.Method = "POST";
hwr.ContentType = "text/xml";
hwr.ContentLength = encData.Length;
Stream send = hwr.GetRequestStream();
send.Write(encData, 0, encData.Length);
send.Close();
hwr.GetResponse();
MonoDevelop: 2.8.5
Mono: 2.10.8
Symptom: System libraries not found (System.DllNotFoundException: libc.dylib)
when a mono created .app is started outside of MonoDevelop.
In the wrapper-script created by mono develop: MyApp.app/Contents/MacOS/MyApp
DYLD_FALLBACK_LIBRARY_PATH is set without including default. Since an empty
DYLD_FALLBACK_LIBRARY_PATH means the default this will remove default. System
libraries cannot be found.
In my opition the line should be:
export DYLD_FALLBACK_LIBRARY_PATH="$MONO_FRAMEWORK_PATH/lib:$DYLD_FALLBACK_LIBRARY_PATH:$(HOME)/lib:/usr/local/lib:/lib:/usr/lib"
Or a check if DYLD_FALLBACK_LIBRARY_PATH is empty would be even better.
I filed a bug-report: http://bugzilla.xamarin.com/show_bug.cgi?id=2727