using System;
using System.Collections;
using System.Net;
using System.Linq;
namespace iReaper.IndexBuilder.WWESource{
public class WWEIdentity
{
#region consts
const int DARREALM = 0;
const int DALOGIN = 1;
const int DAREG = 2;
const int PROPERTIES = 3;
const int GENERALDIR = 4;
const int HELP = 5;
const int CONFIGVERSION = 6;
const string MICROSOFTURL = "https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=11&rver=4.5.2130.0&wp=mcmbi&wreply=https:%2f%2fmsevents.microsoft.com%2fcui%2fdefault.aspx%3fculture%3den-us&lc=1033&cb=wizid%3df4502d34-3b8f-4a04-b741-289e08aa1782%26brand%3dmicrosoft%26returnurl%3dhttps%253a%252f%252fmsevents.microsoft.com%252fcui%252fdefault.aspx%253fculture%253den-us%26wp%3dmcmbi%26lcid%3d1033&id=74335";
#endregion
#region static
private static ArrayList PassportUrls;
private static bool isInited;
/// <summary>
/// Get login server address
/// </summary>
/// <returns></returns>
static WWEIdentity()
{
isInited = GetLoginServerAddres();
}
/// <summary>
/// This function asks a valid login adres, to connect to
/// </summary>
/// <returns>true if succeed</returns>
private static bool GetLoginServerAddres()
{
// Make a request to the server, this adresses are being used in the MSN messenger
HttpWebRequest ServerRequest = (HttpWebRequest)WebRequest.Create("https://nexus.passport.com/rdr/pprdr.asp");
// Get the postData
HttpWebResponse ServerResponse = (HttpWebResponse)ServerRequest.GetResponse();
if (ServerResponse.StatusCode == HttpStatusCode.OK)
{
string retrieveddata = ServerResponse.Headers.ToString();
PassportUrls = new ArrayList();
// Pick up the header en split
string[] result = ServerResponse.Headers.Get("PassportURLs").Split(',');
foreach (string s in result)
{
// The actual adres is provided behind the '=' sign
PassportUrls.Add(s.Substring(s.IndexOf('=') + 1));
}
ServerResponse.Close();
return true;
}
else
{
ServerResponse.Close();
return false;
}
}
/// <summary>
/// This function connects to a login server to request a valid ticket,
/// that will be used to login on the MSN servers
/// </summary>
/// <param name="Password">The password of the user, this is just plain text. The connection is HTTPS
/// <param name="Username">The complete username</param>
/// <param name="ChallengeString">A challenge string that you have got, wile connecting to a msn server
/// <returns>a valid ticket, that you send back to the server to get connected</returns>
private static string GetClientTicket(string Password, string Username, string ChallengeString, out CookieContainer oCookies)
{
oCookies = new CookieContainer();
// First get a valid login adres for the initial server
if (isInited)
{
// On the position of DALOGIN is a valid URL, for login
string uri = "https://" + PassportUrls[DALOGIN];
HttpWebRequest ServerRequest;
HttpWebResponse ServerResponse;
try
{
while (true)
{
Console.WriteLine("Connecting to: " + uri);
// Make a new request
ServerRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
ServerRequest.AllowAutoRedirect = false;
ServerRequest.Pipelined = false;
ServerRequest.KeepAlive = false;
ServerRequest.ProtocolVersion = new Version(1, 0);
ServerRequest.CookieContainer = oCookies;
// Send the authentication header
ServerRequest.Headers.Add("Authorization", "Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmsevents%2Emicrosoft%2Ecom,sign-in=" + Username.Replace("@", "%40") + ",pwd=" + Password + "," + ChallengeString + "\n");
// Pick up the postData
ServerResponse = (HttpWebResponse)ServerRequest.GetResponse();
oCookies.Add(ServerResponse.Cookies);
// If the statuscode is OK, then there is a valid return
if (ServerResponse.StatusCode == HttpStatusCode.OK)
{
string setCookies = ServerResponse.Headers[HttpResponseHeader.SetCookie];
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex("PPAuth=(?<PPAuth>[^;]+);");
var match = regex.Match(setCookies);
string result = null;
if (match.Success)
{
result = match.Groups["PPAuth"].Value;
}
// Close connection
ServerResponse.Close();
// Generate a new substring and return it
return result;
}
// If the statuscode is 302, then there is a redirect, read the new adres en connect again
else if (ServerResponse.StatusCode == HttpStatusCode.Found)
{
uri = ServerResponse.Headers.Get("Location");
}
}
}
catch (WebException e)
{
// If the statuscode is 401, then an exeption occurs
// Think that your password + username combination is not correct
// return number so that calling functions knows what to do
if (e.Status == WebExceptionStatus.ProtocolError)
{
return "401";
}
else
{
return "0";
}
}
}
return "0";
}
#endregion
#region field
private Guid[] _passedGuidList;
private CookieContainer _cookies;
private bool _isLogon;
private string _userName;
private string _password;
// Create a WWEIdentity
// By default not logon
public WWEIdentity(string username, string password)
{
_userName = username;
_password = password;
}
public void Logon()
{
// Live service first
CreatePPCookies();
// Microsoft second
CreateMSCookies();
}
/// <summary>
/// Get cookies which has credential data
/// </summary>
public CookieContainer Cookie { get { return _cookies; } }
// Check if response cookie contains valid information
public bool VerifyCookie()
{
// Get cookies of msevents
var cookies = _cookies.GetCookies(new Uri("https://msevents.microsoft.com"));
// Check if there is MSPAuth and MSPProf
bool auth = false, prof = false;
foreach (Cookie c in cookies)
{
if (c.Name.ToLower().Equals("mspauth") && !string.IsNullOrEmpty(c.Value))
{
auth = true;
}
else if (c.Name.ToLower().Equals("mspprof") && !string.IsNullOrEmpty(c.Value))
{
prof = true;
}
}
if (!auth || !prof)
{
Console.WriteLine("Identity broke, re-logon");
// Something wrong, logon again
Logon();
return false;
}
return true;
}
/// <summary>
/// Go to live service to do a authentication, get PPAuth under login.live.com
/// </summary>
/// <returns></returns>
private void CreatePPCookies()
{
if (!isInited)
{
throw new ApplicationException("Not initialized.");
}
var ppauth = GetClientTicket(_password, _userName, "", out _cookies);
if (ppauth == "401")
{
throw new ApplicationException("Invalid username or passowrd");
}
else if (ppauth == "0")
{
throw new ApplicationException("Falt error");
}
string uriString = "https://" + PassportUrls[DALOGIN];
Uri uri = new Uri(uriString);
Cookie cookie = new Cookie("PPAuth", ppauth);
cookie.Domain = uri.Host;
cookie.Secure = true;
_cookies.Add(cookie);
}
/// <summary>
/// Go to msevents.microsoft.com to get MSPAuth and other related cookies.
/// </summary>
private void CreateMSCookies()
{
// access msevents to get mspauth and mspprof
CookieAwareWebClient client = new CookieAwareWebClient();
client.Cookies = _cookies;
string content = client.DownloadString(MICROSOFTURL);
bool retry = true;
int count = 0;
while (retry)
{
try
{
// Parse html and do the redirect
FormParser parser = new FormParser(content);
if (parser.Forms == null || parser.Forms.Length == 0)
{
throw new ApplicationException("Fault error while try to get MSPAuth");
}
// This is a jscript drived redirection, which contains tickets for msevents
var form = parser.Forms[0];
var result = form.Submit(client);
#if DEBUG
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(result);
string titile = doc.DocumentNode.SelectSingleNode("//title").InnerText;
System.Diagnostics.Debug.Assert(!titile.ToLower().Contains("not authenticated"));
#endif
return;
}
catch (System.Net.WebException webEx)
{
if (webEx.Response is HttpWebResponse)
{
var httpResponse = (HttpWebResponse)webEx.Response;
int statue = (int)httpResponse.StatusCode / 100;
if (statue == 6 || statue == 5)
{
if (count > 5)
{
throw;
}
else
{
retry = true;
count++;
Console.WriteLine("Failed {0} in CreateMSCookies, waiting 1 minutes and try again", count);
// Sleep for 1 minutes
System.Threading.Thread.Sleep(new TimeSpan(0, 1, 0));
}
}
}
else
{
throw;
}
}
}
}
#endregion
}
}
|