I'm working on my own Jabber client (mostly to learn both XMPP and C#) and currently I'm trying to connect to server using SCARAM-SHA-1 over TLS. TLS negotiation goes fine as well as First Client/Server messages exchange, I get Server Challenge and generating Client Final Message with following code:
//Following block generates Client Final Message
//---STEP 1. Creating Salted Password---
byte[] SaltBytes = Encoding.UTF8.GetBytes(Salt);
byte[] SaltedPasswordBytes = GetSaltedPassword(UserPassword, Convert.FromBase64String(Salt), Iterations);
//---STEP 2. Creating Client Key---
byte[] ClientKeyBytes = GetHash("Client Key", SaltedPasswordBytes);
string ClientKey = BitConverter.ToString(ClientKeyBytes);
//---STEP 3. Creating Stored Key---
SHA1 StoredKeySHA = SHA1.Create();
byte[] StoredKeyBytes = StoredKeySHA.ComputeHash(ClientKeyBytes);
string StoredKey = BitConverter.ToString(StoredKeyBytes);
//---STEP 4. Creating Auth Message---
string AuthMessage = "n=test_guy,r=" + ClientNonce + "," + ServerChallenge + "," + "c=" + StringToBase64("n,,") + ",r=" + ClientAndServerNonces; //concern: AuthMessage might start with "n=<username>" or "n,,n=<username>" - which one is right?
LogRTB.Text += "AuthMessage is:\n" + AuthMessage + "\n";
//---STEP 5. Creating Client Signature---
byte[] ClientSignatureBytes = GetHash(AuthMessage, StoredKeyBytes);
string ClientSignature = BitConverter.ToString(ClientSignatureBytes);
//---STEP 6. Creating Client Proof---
LogRTB.Text += "---STEP 6. Calculating Client Proof---\n" + "Client Key is: " + ClientKey + "\nClientSignature is: " + ClientSignature;
byte[] ClientProofBytes = new byte[ClientKeyBytes.Length];
for (int i = 0; i < ClientKeyBytes.Length; ++i)
{
ClientProofBytes[i] = (byte)(ClientKeyBytes[i] ^ ClientSignatureBytes[i]);
}
LogRTB.Text += "\nClient Proof (string) is: " + ClientProof + "\n";
//---STEP 7. Creating Server Key---
byte[] ServerKeyBytes = GetHash("Server Key", SaltedPasswordBytes);
string ServerKey = BitConverter.ToString(ServerKeyBytes);
LogRTB.Text += "Server Key is: " + ServerKey + "\n";
//---STEP 8. Creating Server Signature---
byte[] ServerSignatureBytes = GetHash(AuthMessage, ServerKeyBytes);
string ServerSignature = Convert.ToBase64String(ServerSignatureBytes);
//DONE!
ClientProof = StringToBase64(ClientProof);
string ClientResponse = "c=biws,r=" + ClientAndServerNonces +",p=" + ClientProof; //putting together Client Response (most important part of Client Final Message)
//ClientResponse.Replace("==",""); //NO! just no!
LogRTB.Text += "Client response is:\n" + ClientResponse + "\n"; //DEBUG!
string ClientResponseBase64 = StringToBase64(ClientResponse);
if (IsBase64String(ClientResponseBase64))
{
string ClientFinalMessage = "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + ClientResponseBase64 + "</response>";
LogRTB.Text += "--> Client response (Client Final Message) is:\n" + ClientFinalMessage + "\n";
LogRTB.Text += "--> SENDING NOW!\n";
ServerReply = SendXMPPQueryOverTLS(ServerSocket, SecureConnection, ClientFinalMessage); //Sending Client Final Message
LogRTB.Text += ServerReply;
}
Problem is - I don't get ANY reply from the server, when according to RFC6120 (XMPP Core) server is supposed to reply with failure or success message. Also, if I deliberately send wrong message (for instance omitting Client Proof) it does reply with bad-protocol message. Server is ejabberd with default settings.
I spent couple of days trying to figure out what's wrong and now getting a bit desperate. I hope someone here will be able to help me.
(If needed I can also provide logs that my app generates during connection process)
Thanks in advance!
I have tested agsXMPP SCRAM implementation and it works good with ejabberd. Try to compare with your code - https://github.com/meebey/agsxmpp/blob/master/agsxmpp/Sasl/Scram/ScramSha1Mechanism.cs
Related
I am working on a web application and it needs to track a location using an IP Address and I am new to sending requests to some APIs and getting a response from them. I was able to retrieve IP address of the user using Request.UserHostAddress
and was able to validate it using the following C# code
if (System.Text.RegularExpressions.Regex.IsMatch(ip, "[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"))
{
string[] ips = ip.Split('.');
if (ips.Length == 4 || ips.Length == 6)
{
if (System.Int32.Parse(ips[0]) < 256 && System.Int32.Parse(ips[1]) < 256
& System.Int32.Parse(ips[2]) < 256 & System.Int32.Parse(ips[3]) < 256)
return true;
else
return false;
}
else
return false;
}
else
return false;
and I have got the API key and IP address required to request the following API
http://api.ipinfodb.com/v2/ip_query.php?key=[API KEY]&ip=[IP Address]&timezone=false
I know an HTTP GET REQUEST to the above would give me an XML response but not sure how to get started with the HTTP REQUEST in ASP.NET MVC using C#.
Can someone help me get started with this?
The response of IPInfoDB is a string like below:
OK;;74.125.45.100;US;United States;California;Mountain
View;94043;37.406;-122.079;-07:00
So we need to split into the various fields using C# codes below.
string key = "Your API key";
string ip = "IP address to check";
string url = "http://api.ipinfodb.com/v3/ip-city/?key=" + key + "&ip=" + ip;
HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(string.Format(url));
webReq.Method = "GET";
HttpWebResponse webResponse = (HttpWebResponse)webReq.GetResponse();
Stream answer = webResponse.GetResponseStream();
StreamReader response = new StreamReader(answer);
string raw = response.ReadToEnd();
char[] delimiter = new char[1];
delimiter[0] = ';';
string[] rawdata = raw.Split(delimiter);
ViewData["Response"] = "Country Code: " + rawdata[3] + " Country Name: " + rawdata[4] + " State: " + rawdata[5] + " City: " + rawdata[6];
response.Close();
I am trying to create a C# application that logs in to a Pinger Textfree account and can send SMS messages from it. The web version of this service is flash-based so I have been using Fiddler and Wireshark to monitor the HTTP requests that it uses. I have written some code that I think should log in but I get a "Bad Credentials" response from the server, however, I do know that the username and password I am using are accurate. I am also pretty sure that they do not append anything extra to either as I would have seen this in Fiddler.
static void Main(string[] args)
{
// Connect as client to port 443
string server = "api.pinger.com";
TcpClient client = new TcpClient(server, 443);
// Create a secure stream
using (SslStream sslStream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(ValidateServerCertificate), null))
{
sslStream.AuthenticateAsClient(server);
byte[] data = System.Text.Encoding.ASCII.GetBytes("POST https://api.pinger.com/1.0/web/login HTTP/1.1\r\n" +
"Host: api.pinger.com\r\n" +
"Connection: keep-alive\r\n" +
"Origin: http://pinger.com\r\n" +
"X-Rest-Method: POST\r\n" +
"Authorization: OAuth realm=\"https://api.pinger.com\", oauth_consumer_key=\"textfree-in-flash-web-free\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"HNN8gdLdskKnrtK2jbyN68b9JWQ%3D\", oauth_timestamp=\"1406102776\", oauth_nonce=\"635733471764340000\"\r\n" +
"Content-Type: application/json\r\n" +
"Accept: */*\r\n" +
"Referer: http://pinger.com/tfw/textFree_web.swf\r\n" +
"Accept-Encoding: gzip,deflate,sdch\r\n" +
"Accept-Language: en-US,en;q=0.8\r\n\r\n" +
//json info
"{\"password\":\"testing\",\"username\":\"myquestion\",\"clientId\":\"textfree-in-flash-web-free-1406143265-10D066F9-8126-CD00-4C3D-64AB7BA4FF52\"}\r\n"
);
sslStream.Write(data);
data = new byte[client.ReceiveBufferSize];
int bytesRead = -1;
do
{
bytesRead = sslStream.Read(data, 0, data.Length);
using (MemoryStream ms = new MemoryStream(data, 0, bytesRead))
using (StreamReader rd = new StreamReader(ms))
{
string returnData = rd.ReadToEnd();
Console.WriteLine(returnData);
}
} while (bytesRead != 0);
Console.ReadKey();
}
}
PS I created the account with these credentials (User: myquestion, Pass: testing) just for this question so they are correct and it should be working.
I am using the headers and formatting that the requests I recorded with Fiddler used.
My guesses as to why this attempt has failed is that I am either not posting the json correctly or the authorization header is incorrect or its the "clientId" key in the json. I have done a lot of trial and error as well as research and any help would be appreciated.
I have download toast notification sample code from microsoft site but the code is not executed properly -- giving an error in httpwebresponse --
protected void ButtonSendToast_Click(object sender, EventArgs e)
{
try
{
// Get the Uri that the Microsoft Push Notification Service returns to the Push Client when creating a notification channel.
// Normally, a web service would listen for Uri's coming from the web client and maintain a list of Uri's to send
// notifications out to.
string subscriptionUri = TextBoxUri.Text.ToString();
HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(subscriptionUri);
// We will create a HTTPWebRequest that posts the toast notification to the Microsoft Push Notification Service.
// HTTP POST is the only allowed method to send the notification.
sendNotificationRequest.Method = "POST";
// The optional custom header X-MessageID uniquely identifies a notification message.
// If it is present, the // same value is returned in the notification response. It must be a string that contains a UUID.
// sendNotificationRequest.Headers.Add("X-MessageID", "<UUID>");
// Create the toast message.
string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\">" +
"<wp:Toast>" +
"<wp:Text1>" + TextBoxTitle.Text.ToString() + "</wp:Text1>" +
"<wp:Text2>" + TextBoxSubTitle.Text.ToString() + "</wp:Text2>" +
"<wp:Param>/Page2.xaml?NavigatedFrom=Toast Notification</wp:Param>" +
"</wp:Toast> " +
"</wp:Notification>";
// Sets the notification payload to send.
byte[] notificationMessage = Encoding.Default.GetBytes(toastMessage);
// Sets the web request content length.
sendNotificationRequest.ContentLength = notificationMessage.Length;
sendNotificationRequest.ContentType = "text/xml";
sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "toast");
sendNotificationRequest.Headers.Add("X-NotificationClass", "2");
using (Stream requestStream = sendNotificationRequest.GetRequestStream())
{
requestStream.Write(notificationMessage, 0, notificationMessage.Length);
}
// Send the notification and get the response.
HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse(); // Exception in this line
string notificationStatus = response.Headers["X-NotificationStatus"];
string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
// Display the response from the Microsoft Push Notification Service.
// Normally, error handling code would be here. In the real world, because data connections are not always available,
// notifications may need to be throttled back if the device cannot be reached.
TextBoxResponse.Text = notificationStatus + " | " + deviceConnectionStatus + " | " + notificationChannelStatus;
}
catch (Exception ex)
{
TextBoxResponse.Text = "Exception caught sending update: " + ex.ToString();
}
}
}
I tried running this code in vs 2010 and vs 2013 express but still got the same error
I am working on C# MailClient and which is follow IMAP Protocol, but I am getting wrong response that means the response will give me some repetitive resul.
Like say first time I am sending command like this.
byte[] commandBytes = System.Text.Encoding.ASCII.GetBytes(("$ UID FETCH " + index + " (BODY[HEADER.FIELDS (SUBJECT FROM DATE)])\r\n"));
and second time I am sending like this.
byte[] commandBytes = System.Text.Encoding.ASCII.GetBytes(("$ UID FETCH " + index + " (BODYSTRUCTURE)" + "\r\n"));
so I am getting again first command result in twice or more than 2 times;
and some times it's continue giving me first result.
my Response() method is like this.
private string Response()
{
string response = string.Empty;
byte[] data = new byte[_imapClient.ReceiveBufferSize];
int ret = _imapNs.Read(data, 0, data.Length);
response = Encoding.ASCII.GetString(data,0,ret);
return response;
}
_imapClient is a object of an
private TcpClient _imapClient;
and I am taking value of _imapClient is like this.
public string GetMessageBodyStructure(int index)
{
byte[] commandBytes = System.Text.Encoding.ASCII.GetBytes(("$ UID FETCH " + index + " (BODYSTRUCTURE)" + "\r\n"));
_imapNs.Write(commandBytes, 0, commandBytes.Length);
_imapNs.Flush();
return Response();
}
Where I am wrong correct me thanks..
Do not use char array:
byte[] commandBytes = System.Text.Encoding.ASCII.GetBytes("$ UID FETCH " + index + " (BODYSTRUCTURE)" + "\r\n");
TCP is stream based and not message based.
This means that nothing guarantees that the entire message is received with the same Read. A Read may receive a half message, a complete message or two messages. You need to handle that accordingly.
3 Use return Encoding.ASCII.GetString(data, 0, ret);
4 There are several open source IMAP libraries out there. Why not use one of those since you are new to socket programming?
I am having the following code to Save message to Exchange WEBDAV Drafts folder. IT saves the message but If open it in Outlook, Send button is Disabled and the message is readonly. Please help me find what am i missing in this code...
thanks
Bhuvan
strBody = "To: " + strTo + "\n" +
"Subject: " + (string.IsNullOrEmpty(message.Subject) ? "" : message.Subject) + "\n" +
"Date: " + System.DateTime.Now + "\n" +
"X-Mailer: test mailer" + "\n" +
"MIME-Version: 1.0" + "\n" +
"Content-Type: text/html;" + "\n" +
"Charset = \"iso-8859-1\"" + "\n" +
"Content-Transfer-Encoding: 8bit" + "\n" +
"\n" + (string.IsNullOrEmpty(message.HtmlBody) ? "" : message.HtmlBody.Replace("<head />","").Replace("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">",""));
// Create the HttpWebRequest object.
PUTRequest = (System.Net.HttpWebRequest)HttpWebRequest.Create(tgtUri);
// Add the network credentials to the request.
// Use default credentials of the service to access the server.
PUTRequest.Credentials = cred;
// Specify the PUT method.
PUTRequest.Method = "PUT"; //PROPPATCH
// Encode the body using UTF-8.
byte[] bytes = Encoding.UTF8.GetBytes((string)strBody);
// Set the content header length. This must be
// done before writing data to the request stream.
PUTRequest.ContentLength = bytes.Length;
// Get a reference to the request stream.
PUTRequestStream = PUTRequest.GetRequestStream();
// Write the message body to the request stream.
PUTRequestStream.Write(bytes, 0, bytes.Length);
// Close the Stream object to release the connection
// for further use.
PUTRequestStream.Close();
// Set the Content-Type header to the RFC 822 message format.
PUTRequest.ContentType = "message/rfc822";
// PUT the message in the Drafts folder of the
// sender's mailbox.
PUTResponse = (System.Net.HttpWebResponse)PUTRequest.GetResponse();
if (message.Attachments != null)
{
//Do the PROPPATCH
System.Net.HttpWebRequest PROPPATCHRequest;
System.Net.WebResponse PROPPATCHResponse;
System.IO.Stream PROPPATCHRequestStream = null;
string strxml = "<?xml version='1.0'?>" +
"<d:propertyupdate xmlns:d='DAV:'>" +
"<d:set>" +
"<d:prop>" +
"<isCollection xmlns='DAV:'>False</isCollection>" +
"</d:prop>" +
"</d:set>"
+ "<g:remove>"
+ "<g:prop><m:date/></g:prop>"
+ "</g:remove>"
+ "</d:propertyupdate>";
PROPPATCHRequest = (System.Net.HttpWebRequest)HttpWebRequest.Create(tgtUri);
PROPPATCHRequest.Credentials = cred;
PROPPATCHRequest.Headers.Set("Translate", "f");
PROPPATCHRequest.ContentType = "text/xml";
PROPPATCHRequest.ContentLength = strxml.Length;
PROPPATCHRequest.Method = "PROPPATCH";
byte[] PROPPATCHbytes = Encoding.UTF8.GetBytes(strxml);
PROPPATCHRequest.ContentLength = PROPPATCHbytes.Length;
PROPPATCHRequestStream = PROPPATCHRequest.GetRequestStream();
PROPPATCHRequestStream.Write(PROPPATCHbytes, 0, PROPPATCHbytes.Length);
PROPPATCHRequestStream.Close();
PROPPATCHResponse = (System.Net.HttpWebResponse)PROPPATCHRequest.GetResponse();
foreach (KeyValuePair<string, byte[]> attachment in message.Attachments)
{
System.IO.Stream PUTAttachRequestStream = null;
System.Net.HttpWebRequest PUTAttachRequest;
System.Net.WebResponse PUTAttachResponse;
//Attach File: This could be put in a loop to attach more than one file.
string FileName = attachment.Key; //#"2842498_794802035296_Label1.pdf";
string attachURI = tgtUri + "/" + FileName;
PUTAttachRequest = (System.Net.HttpWebRequest)HttpWebRequest.Create(attachURI);
PUTAttachRequest.Credentials = cred;
PUTAttachRequest.Method = "PUT";
PUTAttachRequest.ContentLength = attachment.Value.Length; //binaryData.Length;
PUTAttachRequestStream = PUTAttachRequest.GetRequestStream();
PUTAttachRequestStream.Write(attachment.Value, 0, attachment.Value.Length); //(binaryData, 0, binaryData.Length);
PUTAttachRequestStream.Close();
PUTAttachResponse = (System.Net.HttpWebResponse)PUTAttachRequest.GetResponse();
PUTAttachResponse.Close();
}
PROPPATCHResponse.Close();
}
// Clean up.
PUTResponse.Close();
I found the answer in Akash's blog on msdn. One has to carefully read this to get the actual answer, but the solution worked.