Connect to facebook chat using Jabber.net (C#/Mono) with SASL - c#

I am trying to connect to facebook chat using Jabber.net(c#/Mono). The code I am using is this:
static ManualResetEvent done = new ManualResetEvent(false);
const bool VERBOSE = true;
const string TARGET = "friends_username#chat.facebook.com";
void Start ()
{
JabberClient j = new JabberClient();
j.User = "my_facebook_alias"; //Later to be removed
j.Server = "chat.facebook.com";
j.Port = 5222;
j.NetworkHost = "chat.facebook.com";
j.AutoStartCompression = true;
j.KeepAlive = 30F;
j.AutoStartTLS = false;
j.AutoStartCompression = true;
j.PlaintextAuth = true;
j.Password = "my_facebook_password"; //Later to be removed
j.RequiresSASL = true;
j.LocalCertificate = null;
// don't do extra stuff, please.
j.AutoPresence = false;
j.AutoRoster = true;
j.AutoReconnect = -1;
j.OnInvalidCertificate += new System.Net.Security.RemoteCertificateValidationCallback(j_OnInvalidCertificate);
// listen for errors. Always do this!
j.OnError += new bedrock.ExceptionHandler(j_OnError);
// what to do when login completes
j.OnAuthenticate += new bedrock.ObjectHandler(j_OnAuthenticate);
// listen for XMPP wire protocol
if (VERBOSE)
{
j.OnReadText += new bedrock.TextHandler(j_OnReadText);
j.OnWriteText += new bedrock.TextHandler(j_OnWriteText);
}
// Set everything in motion
j.Connect();
// wait until sending a message is complete
done.WaitOne();
// logout cleanly
j.Close();
}
static void j_OnWriteText(object sender, string txt)
{
if (txt == " ") return; // ignore keep-alive spaces
Console.WriteLine("SEND: " + txt);
}
static void j_OnReadText(object sender, string txt)
{
if (txt == " ") return; // ignore keep-alive spaces
Console.WriteLine("RECV: " + txt);
}
static void j_OnAuthenticate(object sender)
{
Debug.Log ("OnAuth...");
// Sender is always the JabberClient.
JabberClient j = (JabberClient)sender;
j.Message(TARGET, "My test message!!!");
// Finished sending. Shut down.
done.Set();
}
static void j_OnError(object sender, Exception ex)
{
// There was an error!
Console.WriteLine("Error: " + ex.ToString());
Debug.Log ("Error: "+ex.ToString());
// Shut down.
done.Set();
}
bool j_OnInvalidCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
Debug.Log("Invalid certificate "+sslPolicyErrors.ToString() +" : "+certificate.ToString(true));
return true;
}
I get to j_OnAuthenticate which is good. And it uses my id/password, since changing password to something else makes an error appear. However I do want to use X-FACEBOOK-PLATFORM SASL mechanism to be able to login without saving the users id/password.
The full log is:
RECV: <?xml version="1.0"?><stream:stream id="E34678B6" from="chat.facebook.com" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" xml:lang="en">
RECV: <stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>X-FACEBOOK-PLATFORM</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features>
SEND: <auth mechanism="DIGEST-MD5" xmlns="urn:ietf:params:xml:ns:xmpp-sasl" />
RECV: <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cmVhbG09ImNoYXQuZmFjZWJvb2suY29tIixub25jZT0iMDBENjAwQ0UyNjZBNzgyMEE5MUIzRDhGNjZDODQ1QjMiLHFvcD0iYXV0aCIsY2hhcnNldD11dGYtOCxhbGdvcml0aG09bWQ1LXNlc3M=</challenge>
SEND: <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dXNlcm5hbWU9ImpvbmFzMiIscmVhbG09ImNoYXQuZmFjZWJvb2suY29tIixub25jZT0iMDBENjAwQ0UyNjZBNzgyMEE5MUIzRDhGNjZDODQ1QjMiLGNub25jZT0iMzUzMzMyM2E2YTZmNmU2MTczMzIzYTUxNGU1ZjQxNjI0YzM4NjYiLG5jPTAwMDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvY2hhdC5mYWNlYm9vay5jb20iLHJlc3BvbnNlPTcxN2ExNjM0MzdjOWU5MDM2NDcwYjViNTBhOTYxODIxLGNoYXJzZXQ9dXRmLTg=</response>
RECV: <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cnNwYXV0aD1hM2ZlZGM1NGRmYzNmMGEzMTU5Y2EyZDVmMmVkMmE2Zg==</challenge>
SEND: <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl" />
RECV: <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
SEND: <stream:stream xmlns:stream="http://etherx.jabber.org/streams" id="10996e3a" xmlns="jabber:client" to="chat.facebook.com" version="1.0">
RECV: <?xml version="1.0"?><stream:stream id="2AF2D483" from="chat.facebook.com" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" xml:lang="en">
RECV: <stream:features><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>
SEND: <iq id="JN_1" type="set" to="chat.facebook.com"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><resource>Jabber.Net</resource></bind></iq>
RECV: <iq id="JN_1" type="result"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>jonas2#chat.facebook.com/Jabber.Net_c938c6a2_4C7D6EF9DCFDC</jid></bind></iq>
SEND: <iq id="JN_2" type="set" to="chat.facebook.com"><session xmlns="urn:ietf:params:xml:ns:xmpp-session" /></iq>
RECV: <iq type="result" from="chat.facebook.com" id="JN_2"><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>
OnAuth...
SEND: <message id="JN_3" type="chat" to="friends_username#chat.facebook.com"><body>My test message!!!</body></message>
SEND: <presence type="unavailable"><status>offline</status></presence>
SEND: </stream:stream>
SEND: <iq id="JN_4" type="get"><query xmlns="jabber:iq:roster" /></iq>
In MatriX XMPP there is a OnBeforeSasl delegate where a custom method can setup the required facebook Sasl properties (like facebook app id, app secret and access token). But there is no such delegate in Jabber.net!
Is there no SASL support i Jabber.net? Or how do you set it up?

there is SASL support in jabber-net, but there is no support for the X-FACEBOOK-PLATFORM SASL mechanism. If you want to use this mechanism you have to extend jabber-net by adding this SASL mechanism.
Facebook is closing the XMPP connection. This can be related to the message you send in the Authenticate event. Try to send your message after jabber-net sent your initial presence, or after you got your roster.
Alex

Related

WCF Self-hosted Commandline return 503 error

Hope that you'll be able to help me!
I have a Self-hosted WCF Commandline through https with X509 certificate and I always get a Http 503 error. OS is currently Windows 8.1 with VS Community 2015. At the end, this commandline will be integrated in a Windows Service...
My C# code for WCF Service is this one:
using System;
using System.ServiceModel;
using WCF_Service_Library; //Contract and operations are defined in this library
using System.Threading;
using System.Globalization;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel.Description;
using System.Net;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;
namespace Service_Commandline
{
class Program
{
static void Main(string[] args)
{
ServiceHost serviceHost;
//Get base Url for Web Service WCF
string addressHttps;
string CurrentDnsHostName = Dns.GetHostEntry("").HostName;
addressHttps = String.Format("https://" +CurrentDnsHostName + ":443");
BasicHttpBinding wsHttpBinding =new BasicHttpBinding();
wsHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;
serviceHost = new ServiceHost(typeof(PCsService), new Uri(addressHttps));
//Add service endpoint
Type endpoint = typeof(IPCsService);
serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "WCF");
//Search for X509 certificate
X509Certificate2 certFound = FindX509Certificate("server");
if (certFound!=null)
serviceHost.Credentials.ServiceCertificate.Certificate=certFound;
serviceHost.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
Uri uri = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");
//Add a behavior linked to Mex endpoint
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpsGetEnabled = true;
smb.HttpsGetUrl = uri;
serviceHost.Description.Behaviors.Add(smb);
Console.Out.WriteLine("Mex address " + smb.HttpsGetUrl);
try
{
serviceHost.Open();
string address = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;
Console.WriteLine("Listening # {0}", address);
//Certificate is:
Assembly assembly = typeof(Program).Assembly;
GuidAttribute attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
string appIdInString = attribute.Value;
Console.WriteLine("AppId is: " + appIdInString);
if (certFound != null)
{
Console.WriteLine("Certificate is: " + certFound.FriendlyName);
Console.WriteLine("Certificate thumbprint is: " + certFound.Thumbprint);
}
else
{
Console.WriteLine("No certificate used...");
}
Console.WriteLine("Press enter to close the service");
Console.ReadLine();
}
catch (CommunicationException ce)
{
Console.WriteLine("A commmunication error occurred: {0}", ce.Message);
Console.WriteLine();
}
catch (Exception ex)
{
Console.WriteLine("An unforseen error occurred: {0}", ex.Message);
Console.ReadLine();
}
finally
{
//Close WCF service whatever error found
if (serviceHost != null && serviceHost.State!=CommunicationState.Closed)
serviceHost.Close();
}
}
private static X509Certificate2 FindX509Certificate(string wCFServerName, StoreName storeName=StoreName.My, StoreLocation storeLocation=StoreLocation.LocalMachine)
{
//Find valid certificate
X509Certificate2Collection searchForCurrentServerCertificate = new X509Certificate2Collection();
X509Certificate2 certFound = new X509Certificate2();
X509Store store=null;
try
{
store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadOnly);
searchForCurrentServerCertificate = store.Certificates.Find(X509FindType.FindBySubjectName, wCFServerName, true);
certFound = null;
if (searchForCurrentServerCertificate != null && searchForCurrentServerCertificate.Count > 0)
{
certFound = searchForCurrentServerCertificate[0];
}
store.Close();
}
catch (Exception)
{
if (store != null)
store.Close();
}
return certFound;
}
}
}
Output of this C# code is:
Mex address https:// dev01/WCF/mex
Listening # https:// dev01/WCF
AppId is: f8939c9f-46e7-4d85-ba57-045e68e7fe44
Certificate is: Certificate for this app on port 443
Certificate thumbprint is: 5A26F1C44DE99C0FEB3FB89C80664B9619211696
Press enter to close the service
I've also reserved namespace with cmd:
netsh http add urlacl url= https:// +:443/WCF/ user="\Everyone"
And attach X509 certificate to port 443 with cmd:
netsh http add sslcert ipport=0.0.0.0:443 certhash=5a26f1c44de99c0feb3fb89c80664b9619211696 appid={f8939c9f-46e7-4d85-ba57-045e68e7fe44} certstorename=MY
Finally, these 2 commandlines seems ok according to these outputs:
C:\Windows\system32>netsh http show urlacl url=https:// +:443/WCF/
Réservations d'URL :
--------------------
URL reserved : https:// +:443/WCF/
Utilisateur : \Everyone
Écouter : Yes
Déléguer : No
SDDL : D:(A;;GX;;;WD)
C:\Windows\system32>netsh http show sslcert ipport=0.0.0.0:443
Liaisons de certificat SSL :
----------------------------
Adresse IP:port : 0.0.0.0:443
Hachage du certificat : 5a26f1c44de99c0feb3fb89c80664b9619211696
ID de l'application : {f8939c9f-46e7-4d85-ba57-045e68e7fe44}
Nom du magasin de certificats : : (null)
Vérifier la révocation des certificats clients : Enabled
Vérifier la révocation au moyen du certificat client mis en cache uniquement
 : Disabled
Vérification de l'utilisation : Enabled
Heure d'actualisation de la révocation : 0
Délai d'attente de la récupération d'URL : 0
Identificateur CTL : (null)
Nom du magasin CTL : (null)
Utilisation du mappeur DS : Disabled
Négocier le certificat client : Disabled
And I don't have other reserved Url on https://...443:/WCF/.
Whatever I tried, I get a 503 error on https:// DEV01:443/WCF/.
But mex endpoint seems to be ok on https:// DEV01:443/WCF/Mex.
I get an Xml result. Only one thing seems strange for me in mex Xml: targetNamespace is equal in mex endpoint to "http:// tempuri.org/".
Please help me on this subject!
Regards,
François
I finally found a way to have this Self-hosted Service working.
I don't use anymore parameters in code.
I use an app.config which defined 99% of my serviceHost configuration and just add some piece of parameters in code (like certificate management).
As far as I know this example had 0 chances to work like that!
Lot of guys explain the contrary but they were wrong.
So, with app.config, my code is quite simple:
static void Main(string[] args)
{
ServiceHost serviceHost;
serviceHost = new ServiceHost(typeof(PCsService));
try
{
serviceHost.Open();
...
...
Hope it will help someone else!
Regards.

Exception when subscribing to exchange streaming notifications

I'm currently working on a project that has me integrating with Exchange. One of the requirements is to monitor mailboxes for new incoming messages and I thought that leveraging a streaming notifications would be a good idea.
I wrote a sample application to get familiar with how to leverage streaming notifications, however I am encountering the following error: The expected XML node type was Element, but the actual type is Text.
The following is the source of the sample application that I wrote:
using Microsoft.Exchange.WebServices.Data;
using System;
using System.Net;
namespace ExampleProgram
{
class Program
{
public static StreamingSubscriptionConnection streamingConnection;
public static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
public static void NewMailSubscriptionDisconnect(object sender, SubscriptionErrorEventArgs args)
{
Exception e = args.Exception;
Console.Write("Disconnect: ");
Console.WriteLine(e.Message);
if (streamingConnection != null && !streamingConnection.IsOpen)
{
streamingConnection.Open();
}
}
public static void NewMailSubscriptionError(object sender, SubscriptionErrorEventArgs args)
{
Exception e = args.Exception;
Console.Write("Disconnect: ");
Console.WriteLine(e.Message);
}
public static void NewMailSubscriptionNotification(object sender, NotificationEventArgs args)
{
Console.WriteLine("New message has arrived");
}
static void Main(string[] args)
{
var exchangeService = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
exchangeService.Credentials = new NetworkCredential("username", "password", "domain");
exchangeService.TraceEnabled = true;
exchangeService.TraceFlags = TraceFlags.All;
exchangeService.TraceEnablePrettyPrinting = true;
exchangeService.AutodiscoverUrl("username#example.com", RedirectionUrlValidationCallback);
var newMailSubscription = exchangeService.SubscribeToStreamingNotificationsOnAllFolders(EventType.NewMail);
streamingConnection = new StreamingSubscriptionConnection(exchangeService, 30);
streamingConnection.AddSubscription(newMailSubscription);
streamingConnection.OnNotificationEvent += new StreamingSubscriptionConnection.NotificationEventDelegate(NewMailSubscriptionNotification);
streamingConnection.OnSubscriptionError += new StreamingSubscriptionConnection.SubscriptionErrorDelegate(NewMailSubscriptionError);
streamingConnection.OnDisconnect += new StreamingSubscriptionConnection.SubscriptionErrorDelegate(NewMailSubscriptionDisconnect);
streamingConnection.Open();
do { } while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}
}
As you can see from the above source, I have tracing turned on. The following is what is yielded from those traces:
EwsResponseHttpHeader
<Trace Tag="EwsResponseHttpHeaders" Tid="17" Time="2015-10-20 17:42:31Z">
HTTP/1.1 200 OK
Transfer-Encoding: chunked
request-id: <redacted>
X-CalculatedBETarget: EXAMPLE-EXCHANGE-01.example.com
X-NoBuffering: 1
X-DiagInfo: EXAMPLE-EXCHANGE-01
X-BEServer: EXAMPLE-EXCHANGE-01
Cache-Control: private
Set-Cookie: exchangecookie=<redacted>; path=/,X-BackEndCookie=<redacted>; expires=Thu, 19-Nov-2015 17:42:30 GMT; path=/ews; secure; HttpOnly
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
X-FEServer: EXAMPLE-EXCHANGE-02
Date: Tue, 20 Oct 2015 17:42:30 GMT
</Trace>
EwsResponse
<Trace Tag="EwsResponse"
Tid="15"
Time="2015-10-20 16:52:07Z"
Version="0.0.0.0">
417 <!-- What is this? -->
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<soap11:Header xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
<ServerVersionInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
MajorVersion="15"
MinorVersion="0"
MajorBuildNumber="1130"
MinorBuildNumber="6"
Version="V2_23"
xmlns="http://schemas.microsoft.com/exchange/services/2006/types" />
</soap11:Header>
<soap11:Body xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
<m:GetStreamingEventsResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
<m:ResponseMessages>
<m:GetStreamingEventsResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:ConnectionStatus>OK</m:ConnectionStatus>
</m:GetStreamingEventsResponseMessage>
</m:ResponseMessages>
</m:GetStreamingEventsResponse>
</soap11:Body>
</Envelope>
2 <!-- Not sure what this is either... -->
</Trace>
Exception Detail
Microsoft.Exchange.WebServices.Data.ServiceXmlDeserializationException occurred
HResult=-2146233088
Message=The expected XML node type was Element, but the actual type is Text.
Source=Microsoft.Exchange.WebServices
StackTrace:
at Microsoft.Exchange.WebServices.Data.EwsXmlReader.Read(XmlNodeType nodeType) in C:\Projects\ews-managed-api\Core\EwsXmlReader.cs:line 187
InnerException:
The source of EwsXmlReader.cs can be found at: https://github.com/OfficeDev/ews-managed-api/blob/master/Core/EwsXmlReader.cs
It looks like "something" is prepending 417 and appending 2 to the response from the Exchange server. It's quite obvious to me why the exception is being thrown, there is text data where there shouldn't be. What's not obvious to me, is why that text data is there.
Any ideas?
Transfer-Encoding: chunked
That's the key to this puzzle, you are seeing the "chunks". 417 is a value in hexadecimal for the length of the <Envelope> chunk when you remove the pretty-print formatting. 2 is the final chunk, just whitespace. Chunked transfer formatting is explained here.
I reformatted the XML to remove the white space, You can count off exactly 0x417 = 1047 characters:
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><soap11:Header xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/"><ServerVersionInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" MajorVersion="15" MinorVersion="0" MajorBuildNumber="1130" MinorBuildNumber="6" Version="V2_23" xmlns="http://schemas.microsoft.com/exchange/services/2006/types"/></soap11:Header><soap11:Body xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/"><m:GetStreamingEventsResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"><m:ResponseMessages><m:GetStreamingEventsResponseMessage ResponseClass="Success"><m:ResponseCode>NoError</m:ResponseCode><m:ConnectionStatus>OK</m:ConnectionStatus></m:GetStreamingEventsResponseMessage></m:ResponseMessages></m:GetStreamingEventsResponse></soap11:Body></Envelope>
Obviously the http transfer is supposed to remove them, your question gives no decent lead why this did not happen. But hopefully a pretty good lead to find the underlying cause. Fun puzzle btw :)

Unable to connect to OnVif enabled camera using C#

I am working with IPCams for the first time and I am trying to connect to an OnVif camera. I have looked on various forums and stack overflow and I have come up with the following code.I know the code doesn't do anything useful but it is just a proof of concept for now. It finds all 4 cameras on my network and then I am manually connecting to one of them to pull back some information such as GetServices.
I get a 400 bad response error at this stage. I have looked at the traffic back and forth with WireShark and it appears that everything is working ok regarding the password being generated in so far as I can tell (security and encryption is not my area at all!).
Can anyone help or advise?
class Program
{
static void Main(string[] args)
{
var endPoint = new UdpDiscoveryEndpoint(DiscoveryVersion.WSDiscoveryApril2005);
var discoveryClient = new DiscoveryClient(endPoint);
discoveryClient.FindProgressChanged += discoveryClient_FindProgressChanged;
discoveryClient.FindCompleted += discoveryClient_FindCompleted;
FindCriteria findCriteria = new FindCriteria();
findCriteria.Duration = new TimeSpan(0, 0, 2);//TimeSpan.MaxValue;
findCriteria.MaxResults = int.MaxValue;
discoveryClient.FindAsync(findCriteria);
Console.ReadKey();
}
private static void discoveryClient_FindCompleted(object sender, FindCompletedEventArgs e)
{
Console.WriteLine("Discovery complete");
}
static void discoveryClient_FindProgressChanged(object sender, FindProgressChangedEventArgs e)
{
foreach (var u in e.EndpointDiscoveryMetadata.ListenUris)
{
string uri = u.OriginalString;
if (uri.Contains("http://192.168.1.162/onvif/device_service"))
{
Console.WriteLine(uri);
EndpointAddress serviceAddress = new EndpointAddress(uri);
HttpTransportBindingElement httpBinding = new HttpTransportBindingElement();
httpBinding.AuthenticationScheme = AuthenticationSchemes.Digest;
var messegeElement = new TextMessageEncodingBindingElement();
messegeElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);
CustomBinding bind = new CustomBinding(messegeElement, httpBinding);
DeviceClient client = new DeviceClient(bind, serviceAddress);
// Add our custom behavior - this require the Microsoft WSE 3.0 SDK
PasswordDigestBehavior behavior = new PasswordDigestBehavior("test", "test");
client.Endpoint.Behaviors.Add(behavior);
foreach (Service s in client.GetServices(false))
Console.WriteLine(s.ToString());
client.Open();
Console.WriteLine("WSDL = " + client.GetWsdlUrl());
Console.WriteLine("DateTime = " + client.GetSystemDateAndTime());
string a1, b1, c1, d1;
Console.Write(client.GetDeviceInformation(out a1, out b1, out c1, out d1));
}
}
}
}
Wireshark (username and passwor are both test)
POST /onvif/device_service HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver10/device/wsdl/GetServices"
Host: 192.168.1.162
Content-Length: 1232
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo7uVma6HRQNDh2l6T2ZDNzIAAAAA2/ITWE91IUaNFF3UObayz0mz6QvnZppBlYrNJBd1QGsACQAA</VsDebuggerCausalityData>
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="SecurityToken-56f9081e-e9b4-4660-9158-7419af1efde0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>test</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">WSKWE5XjP5aPiIiA9JicCOYoDkU=</wsse:Password>
<wsse:Nonce>6sYgS41VHsWKj7n8TNKFjA==</wsse:Nonce>
<wsu:Created>2013-08-09T14:52:45Z</wsu:Created>
</wsse:UsernameToken>
</Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetServices xmlns="http://www.onvif.org/ver10/device/wsdl">
<IncludeCapability>false</IncludeCapability>
</GetServices>
</s:Body>
</s:Envelope>HTTP/1.1 400 Bad Request
Server: gSOAP/2.7
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 2751
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:xmime="http://tempuri.org/xmime.xsd" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:wsrfbf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:wsrfr="http://docs.oasis-open.org/wsrf/r-2" xmlns:aa="http://www.axis.com/vapix/ws/action1" xmlns:aev="http://www.axis.com/vapix/ws/event1" xmlns:tan1="http://www.onvif.org/ver20/analytics/wsdl/RuleEngineBinding" xmlns:tan2="http://www.onvif.org/ver20/analytics/wsdl/AnalyticsEngineBinding" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:tev1="http://www.onvif.org/ver10/events/wsdl/NotificationProducerBinding" xmlns:tev2="http://www.onvif.org/ver10/events/wsdl/EventBinding" xmlns:tev3="http://www.onvif.org/ver10/events/wsdl/SubscriptionManagerBinding" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:tev4="http://www.onvif.org/ver10/events/wsdl/PullPointSubscriptionBinding" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tnsaxis="http://www.axis.com/2009/event/topics">
<SOAP-ENV:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo7uVma6HRQNDh2l6T2ZDNzIAAAAA2/ITWE91IUaNFF3UObayz0mz6QvnZppBlYrNJBd1QGsACQAA</VsDebuggerCausalityData>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<SOAP-ENV:Fault SOAP-ENV:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<SOAP-ENV:Code>
<SOAP-ENV:Value>SOAP-ENV:Sender</SOAP-ENV:Value>
<SOAP-ENV:Subcode>
<SOAP-ENV:Value>ter:NotAuthorized</SOAP-ENV:Value>
</SOAP-ENV:Subcode>
</SOAP-ENV:Code>
<SOAP-ENV:Reason>
<SOAP-ENV:Text xml:lang="en">Sender not authorized</SOAP-ENV:Text>
</SOAP-ENV:Reason>
<SOAP-ENV:Detail>
<SOAP-ENV:Text>The action requested requires authorization and the sender is not authorized</SOAP-ENV:Text>
</SOAP-ENV:Detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I have onvif enabled on the camera (by creating an administrator user called "test" with a password "test". The camera password is the default "root" and "pass" as it is an Axis camera.
Configure the connection to the camera this way:
ServicePointManager.Expect100Continue = false;
var endPointAddress = new EndpointAddress("http://" + cameraAddress + "/onvif/device_service");
var httpTransportBinding = new HttpTransportBindingElement { AuthenticationScheme = AuthenticationSchemes.Digest };
var textMessageEncodingBinding = new TextMessageEncodingBindingElement { MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None) };
var customBinding = new CustomBinding(textMessageEncodingBinding, httpTransportBinding);
var passwordDigestBehavior = new PasswordDigestBehavior(adminName, adminPassword);
var deviceClient = new DeviceClient(customBinding, endPointAddress);
deviceClient.Endpoint.Behaviors.Add(passwordDigestBehavior);
I know it's almost what you have done but it is important to make ServicePointManager.Expect100Continue false.
Check if the camera have the replay attack protection enabled. If so check the time difference between your computer's time and the camera's. According to the ONVIF's specs the allowed time difference must be +- 5 seconds. Otherwise you get your error.
If this is your case you have several options:
1- Disable the replay attack protection feature. This is not recommended because you would need to disable this feature in all the cameras you need to work with.
2- You can sync the camera's time with your computer time. Again not recommended for the same issue of the first option.
3- If you can change the WSE 3.0 for other option. In WSE3.0 once you have created the UsernameToken you can't change the Created property, which is used to create the encryption. This problem is described in here

SSL communication between Java and C# applications

My goal is to make a secure communication between a Java server and client written in C#.
java server code:
System.setProperty("javax.net.ssl.keyStore","cert/mySrvKeystore");
System.setProperty("javax.net.ssl.keyStorePassword","myPassword");
SSLServerSocketFactory sslserversocketfactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslserversocket = = (SSLServerSocket) sslserversocketfactory.createServerSocket(2389);
while(true) {
System.err.println("server w8 new connection");
try {
SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();
//sslsocket.startHandshake();
in = sslsocket.getInputStream();
out = sslsocket.getOutputStream();
out.flush();
String response = new String(receiveMessage());
while (response != "end") {
System.out.println("Server recv="+response);
response = new String(receiveMessage());
sendMessage(("echo="+response).getBytes());
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
and client written in c# :
client = new TcpClient() { SendTimeout = 5000, ReceiveTimeout = 5000 };
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(host), port);
client.Connect(serverEndPoint);
client.NoDelay = true;
Console.WriteLine("Client connected.");
// Create an SSL stream that will close the client's stream.
SslStream sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null);
// The server name must match the name on the server certificate.
try
{
sslStream.AuthenticateAsClient("someName");
}
catch (AuthenticationException error)
{
Console.WriteLine("Exception: {0}", error.Message);
if (error.InnerException != null)
{
Console.WriteLine("Inner exception: {0}", error.InnerException.Message);
}
Console.WriteLine("Authentication failed - closing the connection.");
client.Close();
return;
}
ASCIIEncoding ascii = new ASCIIEncoding();
SendData(ascii.GetBytes("Hello World"));
and
public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
// Do not allow this client to communicate with unauthenticated servers.
return false;
}
and i get the following errors: in c#
A first chance exception of type "System.Security.Authentication.AuthenticationException" occurred in System.dll
Certificate error: RemoteCertificateChainErrors
Exception: The remote certificate is invalid according to the validation procedure.
Authentication failed - closing the connection.
I know that the issue can be the fact that i use different types of certificates, but i don't know how to make a standard sslServerSocket with X509Certificate in java. Can some one help me, with good example, or some advice how can i reach my goal ?
P.S. I was looking to bouncycastle library, causes it has both java, and c# implementation, but i would like to use standard libraries, and built-in functionality of the languages.
From your example, it doesn't look like you need to generate your certificate and private key programmatically. You can generate a certificate in your server keystore with keytool:
keytool -genkey -alias myalias -keystore mykeystore.jks -dname "CN=www.example.com"
Or better, with the SAN extension too, if you're using Java 7's keytool:
keytool -genkey -alias myalias -keystore mykeystore.jks -dname "CN=www.example.com" -ext san=dns:www.example.com
Here, www.example.com is the host name as seen by the client. You can add other things in the Subject DN (dname), but make sure the CN is the host name.
Once it's generated, export your self-signed certificate using:
keytool -export myservercert.crt -alias myalias -keystore mykeystore.jks
You should then be able to import it as a trusted certificate in your Windows certificate store from use from C#.

c# LinkedIn API dquail Oauth changing from current-status to new <share> api

I downloaded the dquail-LinkedinOauth-f169b1f from
https://github.com/dquail/LinkedinOauth
I got it working. Problem is - this code uses the old current-status api which is deprecated and limited to 140 characters
https://developer.linkedin.com/documents/status-update-api
and has been replaced by the share api which allows 700 characters plus a lot of other features
https://developer.linkedin.com/documents/share-api
I edited the code to provide the new xml and the new URL - but I get an error. The new code is:
private void btnUpdateStatus_Click(object sender, EventArgs e)
{
try
{
//string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
//xml += "<current-status>" + txtNewStatus.Text + "</current-status>";
string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><share>";
xml += "<comment>" + txtNewStatus.Text + "</comment><visibility><code>anyone</code></visibility></share>";
//string response = _oauth.APIWebRequest("PUT", "http://api.linkedin.com/v1/people/~/current-status", xml);
string response = _oauth.APIWebRequest("PUT", "http://api.linkedin.com/v1/people/~/shares", xml);
if (response == "")
txtResults.Text += "\n\rYour new status updated. view linkedin for status.";
}
catch (Exception exp)
{
txtResults.Text += "\n\rException: " + exp.Message;
}
}
The XML I am sending is:
<?xml version="1.0" encoding="UTF-8" ?>
<share>
<comment>"Theres a lot of blood, sweat, and guts between dreams and success.", Paul Bryant</comment>
<visibility>
<code>anyone</code>
</visibility>
</share>
the error I get is:
"The remote server returned an error: (405) Method Not Allowed."
You're using PUT, but the Share API requires POST as the method.
405 means "You're using an HTTP method this endpoint doesn't support"
As far as why, you're not updating the current status, you're adding a new share.
https://developer.linkedin.com/documents/share-api

Categories