Windows Authentication-enabled IIS Site performs differently with 2 different bindings - c#

I have a site set up in IIS 7, and it is using Windows Authentication as the only enabled Authentication Mode. It utilizes a custom .NET 4 Application Pool - the pool uses the default ApplicationPoolIdentity. This site is a C#/ASP.NET application with its own page authorization rules (generated using Iron Speed Designer 9). I have the two bindings set up below:
servicedirectory.sampledomain.com
booking.sampledomain.com
Both of these bindings are mapped to the site on all available IPs on port 80.
For the most part, browsing through either binding works successfully, except for a certain page where I create a WebRequest that fetches another page as a Stream. (I am taking the other page's contents and embedding them as an attachment in an iCal (.ics) file for inclusion in meeting requests. The file is downloaded and sent out by the user)
String request = Request.Url.GetLeftPart(UriPartial.Path).
Replace("Conference.aspx", "Confirmation.aspx") +
"?Conference=" + conference.ConferenceId;
WebRequest webRequest = WebRequest.Create(request);
webRequest.UseDefaultCredentials = true;
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
Stream newStream = webRequest.GetRequestStream();
// Send the data.
newStream.Close();
WebResponse webResponse = webRequest.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
using (MemoryStream ms = new MemoryStream())
{
responseStream.CopyTo(ms);
attachmentContent = Convert.ToBase64String(ms.ToArray());
}
responseStream.Close();
The problem is the following: this code succeeds and produces the content from the Confirmation.aspx page as String data (attachmentContent variable) when the user is browsing under the first binding (servicedirectory.sampledomain.com). However, I get a 401.1 error at the WebResponse webResponse = webRequest.GetResponse(); line when browsing via the other binding URL. There are no references in the application source code or web.config to either binding - everything was built with the intention of being deployed to any URL.
Why would two different bindings affect this?

Related

Programmatically login to Apple iCloud and Find My Network

I try to programmatically connect to the find-my network (belonging to iCloud) to locate devices attached to my Apple-ID.
This should pe possible using web requests. For example I post a request with my credentials to:
https://setup.icloud.com/setup/ws/1/login
string jsonreq = Newtonsoft.Json.JsonConvert.SerializeObject(temp); //temp is an object with login credentials
byte[] dataStream = Encoding.UTF8.GetBytes(jsonreq);
WebRequest webRequest = WebRequest.Create("https://setup.icloud.com/setup/ws/1/login");
webRequest.Method = "POST";
webRequest.Headers.Set("Origin", "https://www.icloud.com");
webRequest.ContentLength = dataStream.Length;
Stream newStream = webRequest.GetRequestStream();
// Attach the data.
newStream.Write(dataStream, 0, dataStream.Length);
newStream.Close();
WebResponse webResponse = webRequest.GetResponse();
// read server url, dsid, Cookie from response
This is working in the first step, but now I'm facing the problem that 2 factor authentication is to be used for logging in.
Can someone help me/show me next steps in the login process via web request for 2 factor authentication? (Of course I receive the login authentication code on my apple devices)

https request fails only in .net web app

I am trying to patch a .net web application that after years of working started failing to get UPS shipping quotes, which is impacting web business dramatically. After much trial and error, I found the following code that works just fine in a console application:
static string FindUPSPlease()
{
string post_data = "<xml data string>";
string uri = "https://onlinetools.ups.com/ups.app/xml/Rate";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
byte[] postBytes = Encoding.ASCII.GetBytes(post_data);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postBytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
// get response and send to console
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
Console.WriteLine(response.StatusCode);
return "done";
}
This runs in Visual Studio just fine and gets a nice little response from UPS that the XML is, of course, malformed.
But, if I paste this function into the web application without changing a single character, an exception is thrown on request.GetRequestStream():
Authentication failed because the remote party has closed the transport stream.
I tried it in a couple of different place in the application with the same result.
What is there about the web application environment that would affect the request?
It turns out to be a TLS issue. I guess the console app uses a higher protocol by default than the web application, although none was specified. So, all you have to do is add the following line(s) of code sometime prior to making the request:
using System.Net;
...
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
That was all it took, though I spent an enormous amount of getting there.
Here is the response from UPS on the issue:
Effective January 18, 2018, UPS will only accept TLS 1.1 and TLS 1.2 security protocols... 100% of requests from customers who are on TLS 1.0 while using production URLS (onlinetools.ups.com/tool name) will be rejected.
Anyway, hope this helps someone.
Jim
Can you try setting the Credentials to your request object like following.
request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
Try setting the default credentials or check if there is any proxy server set and pass it like in the example below.
The example is given for WebClient.
I was having problem with setting Default Credential, as proxy was enabled on the server. So i passed the proxy URL and port with credentials which can access it.
using (System.Net.WebClient web = new System.Net.WebClient())
{
//IWebProxy defaultWebProxy = WebRequest.DefaultWebProxy;
//defaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
//web.Proxy = defaultWebProxy;
var proxyURI = new Uri(string.Format("{0}:{1}", proxyURL, proxyPort));
//Set credentials
System.Net.ICredentials credentials = new System.Net.NetworkCredential(proxyUserId, proxyPassword);
//Set proxy
web.Proxy = new System.Net.WebProxy(proxyURI, true, null, credentials);
web.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var result = web.UploadString(URL, "");
return result;
}

Accessing HttpRUntime.Cache in console app

I have a console app that needs to dynamically load all the endpoints in my API app and get the details of the data that is cached.
foreach (var routeTemplate in listRouteTempplates)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost/appName/" + routeTemplate );
WebResponse response = null;
Stream dataStream = null;
request.Method = HttpMethod.Get.ToString();
response = request.GetResponse();
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
var count=HttpRuntime.Cache.Count;
}
When invoking each endpoint, the data retrieved is also cached. I confirmed that by calling the endpoints directly (via postman) and checking the cache.
But in the console app, even though the response does have the correct data, the count of items in HttpRuntime.Cache is always zero.
Is there a reason the data is not cached when I call the endpoints in a console app ?
Thanks
The cache in which items are stored lives on the server inside your Web API host. It is then normal that the cache instance that you are checking inside your client console application doesn't have any items in it - those are 2 completely different object instances living in 2 different applications.

Does the WebResponse for Windows Phone 8 skip set-cookie headers

I am experiencing some strange behavior with a Windows Phone 8 app that I am building and I hope someone here has some experience with it.
I am reading a website using a normal HttpWebRequest and expecting a cookie as a response. However, somehow, I am not getting the Set-cookie header back in my WebResponse. I have created the same functionality under WPF and it works as normal - returns the Set-cookie header in the response.
I have also tried looking at the CookieContainer of the response, but it is also empty.
Here is the code that I am using for this. Note: the same piece of code (without the async stuff) works correct in WPF and returns the Set-Cookie header. I can post it as well if necessary:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.mysite.com/login");
request.Method = HttpMethod.Post;
request.AllowAutoRedirect = false;//normally there is a redirect in place
postData = "username=1234&password=2345";
var data = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = await Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null))
{
await stream.WriteAsync(data, 0, data.Length);
stream.Close();
}
using (var response = await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null))
{
return response.Headers["set-cookie"];
}
As a result of this, I am getting some response headers (such as content-type and server specific ones) but not the Set-Cookie one.
I've done some more tests and the set-cookie header is omitted only on the Windows Phone Emulator. When debugging with an actual device, the header is received as expected.
It is still pretty strange to me why the emulator behaves this way. I saw many posts on issues with http-only cookies in the emulator but none with a concrete reason.
UPDATE:
Testing on the 8.0.10322 emulator works just fine - cookies are handled correctly.It looks as the default phone emulator does something fishy with the cookies.

"Hostname could not be parsed" From "ftp" URL

I just purchased some online storage from GoDaddy and I an trying to FTP into my storage account. The thing is, I can view and modify my account using FileZilla, but my C Sharp program will not even access it because of the "hostname could not be parsed" error.
I believe it is because the entire ftp address of my account has two "#" signs in the url, and it is the wreaking havoc in the URI creation process.
Is there anyway I can get around this, or am I screwed because of the naming convention of the GoDaddy storage?
The URL is: ftp:[slashslash]lastname.firstname#gmail.com#onlinefilefolder.com/Home/
Do you need to specify the username and password in the URI for some specific reason? You can simply connect to the host and then provide credentials.
// Create a request to the host
var request = (FtpWebRequest)WebRequest.Create("ftp://onlinefilefolder.com");
// Set the username and password to use
request.Credentials = new NetworkCredential ("lastname.firstname#gmail.com","password");
request.Method = WebRequestMethods.Ftp.UploadFile;
var sourceStream = new StreamReader("testfile.txt");
var fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
response.Close();
The exception is originating from System.Uri, which (despite it being acceptable by the standards definition) will not allow two # symbols.
// This will reproduce the reported exception, I assume it is what your code is
// doing either explicitly, or somewhere internally
new Uri(#"ftp://lastname.firstname#gmail.com#onlinefilefolder.com/Home/")
A potential workaround is to percent-encode the first # symbol, which will allow the Uri instance to be instantiated without exception--but may or may not work depending on the server's behavior (I have only used this approach a couple times, but it has worked for me):
new Uri(#"ftp://lastname.firstname%40gmail.com#onlinefilefolder.com/Home/")

Categories