InternetGetCookieEx: not working - wpf

I am trying to read an HttpOnly cookie through a WPF, VB.NET application.
The site in question, upon visit, serves 2 cookies: one HttpOnly, one regular.
I visit the site whose cookie I want to read via Internet Explorer. Then Developer tools --> Cache --> View cookie information. ONLY the regular cookie is shown there, not the HttpOnly one (Chrome displays both of them correctly. If I delete it and refresh, the site returns a 500 error so the cookie definitely exists).
I run my code, based on what is explained here: c# Get httponly cookie, which is as follows:
Private Const INTERNET_COOKIE_HTTPONLY As Integer = &H2000
<SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("wininet.dll", EntryPoint:="InternetGetCookieExW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True)>
Friend Shared Function InternetGetCookieEx(<[In]> Url As String, <[In]> cookieName As String, <Out> cookieData As StringBuilder, <[In], Out> ByRef pchCookieData As UInteger, flags As UInteger, reserved As IntPtr) As Boolean
End Function
<SecurityCritical()>
Public Shared Function GetCookie(url As String) As String
Dim size As Integer = 0
Dim sb As New StringBuilder
If InternetGetCookieEx(url, vbNullString, Nothing, size, INTERNET_COOKIE_HTTPONLY, IntPtr.Zero) Then '<-- this always returns false
If size <= 0 Then
Return Nothing
End If
sb = New StringBuilder(size + 1)
If Not InternetGetCookieEx(url, vbNullString, sb, size, INTERNET_COOKIE_HTTPONLY, IntPtr.Zero) Then
Return Nothing
End If
End If
Dim lastErrorCode = Marshal.GetLastWin32Error '<-- 259
Return sb.ToString()
End Function
GetCookie("https://www.xyz.com")
I have tried numerous variations of the above, the result is the same: lastErrorCode ALWAYS equals to 259, which in turn translates to ERROR_NO_MORE_ITEMS, meaning that no cookies have been found.
1) The site in question is in the trusted sites zone, so it doesn't work under protected mode.
2) The site is under SSL (I do not know if this has to do with anything).
3) I have desperately searched my hard disk for these cookies' location, to no avail.
4) Both are session cookies (ie no declared expiration date)
5) Windows 8 x64, IE10, VS2012
This is a tiny bit of a project milestone which has given me countless hours of pain, so any help will be greatly appreciated.
I am very willing to change my methodology completely as soon as it will give me this cookie's value, unless it's overkill (ie winpcap / fiddlercore etc.)

You're correct to note that your code would only ever work in the Trusted Zone, due to Q10 here: http://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx since cookies aren't shared between IE (which runs in Protected Mode or AppContainer) and your application (which runs at Medium IL).
You should pass a valid URL into the function (e.g. you need at least a trailing slash after the hostname); even if an invalid URL works today, it might not in the future.
Also keep in mind that you'll only ever see IE's persistent cookies with this code; Session cookies are isolated per-process, so your application won't see Session cookies from an IE tab.

To all whom it may concern:
Eric was absolutely right: Session cookies are in-process, so they are virtually invisible from the outside world.
One possible solution that works is the following:
Load the site in a webbrowser control.
The code I posted works as expected.

Related

Adding a DocumentWindow to a DocumentTabStrip causes the application to hang indefinitely

I have a Winforms application with a primary form that contains (among other things) a Telerik DocumentTabStrip. These tabs are used to hold user controls or web pages (via a web browser control). It has worked fine for quite a while, but I'm running into an issue now.
I recently switched the web browser control from the built-in .NET web browser based on IE to CefSharp. Since doing so, I've noticed that occasionally when trying to add the DocumentWindow to the DocumentTabStrip, the call will hang indefinitely (in debug) or crash outright (running the app normally). This only appears to happen when opening a DocumentWindow that contains the browser control, not any other user controls. The actual call itself is below.
I'm at a bit of a loss as to how to even begin to debug this, since there's no error that gets received - it just hangs inside the Controls.Add() method indefinitely. Any advice would be appreciated.
Private dts As New Telerik.WinControls.UI.Docking.DocumentTabStrip
Try
dts.InvokeIfRequired(Sub()
Dim docWindow As Telerik.WinControls.UI.Docking.DocumentWindow = Nothing
Dim ctrl As ucBaseControl = Nothing
Dim browser As ucBrowser = Nothing
Dim isBrowser As Boolean = False
docWindow = New Telerik.WinControls.UI.Docking.DocumentWindow
docWindow.BackColor = Color.FromArgb(89, 89, 89)
'Do various stuff to determine the type of control to load (ctrl or browser), then setup the applicable control
If isBrowser Then
'Place the browser into the Document Window.
If Not IsNothing(browser) Then
browser.Dock = DockStyle.Fill
docWindow.Controls.Add(browser)
End If
Else
'Place the ctrl into the Document Window.
ctrl.Dock = DockStyle.Fill
docWindow.Controls.Add(ctrl)
End If
'Add the DocumentWindow to the DocumentTabStrip
' Ensure DockWindow not disposed due to lag in bringing up
If IsNothing(docWindow) OrElse docWindow.IsDisposed Then
Exit Sub
End If
Try
docWindow.Padding = New Padding(0)
dts.TabStripElement.Children(0).Children(1).Padding = New Padding(0)
dts.Controls.Add(docWindow) 'This is where the issue is. It only happens sporadically here.
Catch ex As Exception
'Code to log any exceptions here. In the problem described here, no exception is ever generated, though.
End Try
'Bring the control to the front and focus it, here...
End Sub)
Catch ex As Exception
'Error handling code here'
End Try
I'm assuming InvokeIfRequired is an extension method you've created for Controls. Note that if it relies on Invoke, that is a synchronous call, instead use BeginInvoke (see: What's the difference between Invoke() and BeginInvoke())
No exception was ever thrown because you were suffering from deadlock

How to determine in CefSharp that the response from the server is 404?

I am using WPF control for CefSharp. I need to know when the request I made receives a response with http status code 404.
I've noticed that CefSharp has LoadError event, but that only fires when the domain cannot be resolved altogether (i.e. if I go to www.sdfhjkhajsdf.com). It doesn't work for when the domain exists, but the page your requesting doesn't.
This is a pretty old question. CefSharp has had lots of great updates, so I hope this helps others searching like me. Don't hate me because my snippets are in VB.NET. ;)
This is what I'm doing to log anything that is not 200 response. For my application, I open a new form of the requested page, so I limit my focus to the initial page request by looking at the ReferrerUrl property. Obviously, you could drop that part to be alerted to all requests.
When you initially implement your ChromiumWebBrowser you need to set a RequestHandler to your implementation.
Me.chromeBrowser = New CefSharp.WinForms.ChromiumWebBrowser(uri)
Me.chromeBrowser.RequestHandler = New CefBasicRequestHandler()
Me.Controls.Add(Me.chromeBrowser)
CefSharp released a default implementation that you can use and just override OnResourceResponse.
Imports System.Security.Cryptography.X509Certificates
Imports CefSharp
Public Class CefBasicRequestHandler
Inherits CefSharp.Handler.DefaultRequestHandler
Private Shared ReadOnly Logger As log4net.ILog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType)
Public Overrides Function OnResourceResponse(browserControl As IWebBrowser, browser As IBrowser, frame As IFrame, request As IRequest, response As IResponse) As Boolean
If String.IsNullOrWhiteSpace(request.ReferrerUrl) Then ' this is the first request of the page
Dim method As String = "OnResourceResponse()."
Dim requestOverview As String = $"[{response.StatusCode}] [{request.Url}]"
Logger.Info($"{method} {requestOverview}")
If response.StatusCode <> 200 Then
Logger.Warn($"{method} {requestOverview}")
End If
End If
Return MyBase.OnResourceResponse(browserControl, browser, frame, request, response)
End Function
End Class

Getting filenames from a folder in Sharepoint with VBA

I've done alot of research on this and found a number of help sites but still can't understand why this sometimes doesn't work.
I'm trying to access a sharepoint site (to which there are no restrictions for me) and extract all the files in a folder within that site.
Sometimes my Path works and it does it, other times it does not. I have a feeling it works if I've gone into the sharepoint site on my browser before but can't confirm that (because I just tried it again now and it doesnt work ARGGH). But the same code below has worked in the past.
It's failing on the File System Object function below
Public Function GetFullFileName(strfilepath As String, _
strFileNamePartial As String) As String
Dim objFS As Variant
Dim objFolder As Variant
Dim objFile As Variant
Dim intLengthOfPartialName As Integer
Dim strfilenamefull As String
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFS.GetFolder(strfilepath)
'work out how long the partial file name is
intLengthOfPartialName = Len(strFileNamePartial)
For Each objFile In objFolder.Files
'Test to see if the file matches the partial file name
If Left(LCase(Replace(objFile.Name, " ", "")), intLengthOfPartialName) = LCase(strFileNamePartial) Then
'get the full file name
strfilenamefull = objFile.Name
Exit For
Else
End If
Next objFile
'Return the full file name as the function's value
GetFullFileName = strfilenamefull
End Function
I get a "Run-time error '76': Path not found" when it gets to the GetFolder(strfilepath) code
The strfilepath is just a regular sharepoint site name (e.g. like \teams.uk\gm\FX\SharedDocuments\London\11) November 2013\20 November\Reports)
As mentioned I've tried different variations of the file path including DavWWW but nothing seems to work and I dont know what else to try.
Any advice please?
Thanks
Raiyan
The webclient service must be started to Access SharePoint using the FileSystemObject.
This service is often not started when you first log on. However as you access SharePoint via the normal user interface it gets started. I think this is why your code works inconsistently.
If you have admin rights on the local machine you can start the service manually (or using code). However if you don't have rights then you can try a trick - it's clumsy but works.
Using VBA code open a known SharePoint folder in explorer view then close it. This will trigger webclient to start.

How to register own protocol using the WebBrowser control?

In a WP7 Silverlight application with a WebBrowser control I want to use an own protocol like "myttp://" to deliver some local content. I can't use Navigate() to an IsolatedStrorage because some content will by created on demand. For the same reason NavigateToString() is also not usable for me.
I tried to register a WebRequestCreator descend for my MYTP protocol
myCreator = new MyRequestCreator();
WebRequest.RegisterPrefix("mytp://", myCreator);
but it isn't called from the browser control if I navigate to "mytp://test.html".
If I create a WebRequest via code
WebRequest request;
request = WebRequest.Create("mytp://test.html");`
everythings works fine.
Any suggestions what is wrong or how to do it?
The WebBrowser control will use the Windows Phone Internet Explorer Browser's HTTP stack to statisfy web requests. This HTTP stack is entirely separate from the Client HTTP stack being used by the application. Hence the browser does not see your protocol at all.
I agree with AnthonyWJones words, though I dont know, what exactly he meant by "Browser HTTP stack".
The standard Silverlight's "access to Browser's stack" (used to handle sessions etc) in form of System.Net.Browser.WebRequestCreator.BrowserHttp httprequest factory (versus the "normal/aside" System.Net.Browser.WebRequestCreator.ClientHttp factory) is actually available to the application code in WP7. It is hidden from the SDK, but available on the device and with small effort, the application can use it, for example, to have its emitted cookies in sync with the Browser's cache. For description, please see my humble other post
However, while using that factory and having all your session/cookies/userauth handling within those connections in sync with the WebBrowser, despite being very similar to the ClientHttp factory, you find (at least in 7.0 and 7.1 versions) that it is completely ignorant of any custom prefixes. Trying to open anything with this factory results in (WP7 v. Mango 7.1):
A first chance exception of type 'System.Net.ProtocolViolationException' occurred in System.Windows.dll
at System.Net.Browser.BrowserHttpWebRequest.InternalBeginGetRequestStream(AsyncCallback callback, Object state)
at System.Net.Browser.AsyncHelper.BeginOnUI(BeginMethod beginMethod, AsyncCallback callback, Object state)
at System.Net.Browser.BrowserHttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state)
at MyApp.MyPage..ctor()
relevant code snippet of the MyPage:
public class WRC : IWebRequestCreate { public WebRequest Create(Uri uri) { return null;/*BREAKPOINT1*/ } }
WebRequest.RegisterPrefix("js://", new WRC()); // register the above handler
brwHttp = (IWebRequestCreate)typeof(System.Net.Browser.WebRequestCreator).GetProperty("BrowserHttp").GetValue(null, null);
var tmp = brwHttp.Create(new Uri("js://blah.blah.blah"));
var yyy = tmp.BeginGetResponse(callback, "wtf");
var response = tmp.EndGetResponse(yyy); /*BREAKPOINT2*/
var zzz = tmp.BeginGetRequestStream(callback, "wtf"); /*<---EXCEPTION*/
var stream = tmp.EndGetRequestStream(zzz); /*BREAKPOINT3*/
Execution results:
breakpoint1 never hit
breakpoint2 allows to see that "response" is NULL
breakpoint3 never hit due to the exception pasted above
My conclusion is, that the Silverlight Browser's stack is hardcoded to use some builtin set of prefixes, and all other prefixes are ignored/throw ProtocolViolation. My guess is, that in WP7 (7.0, 7.1) they are actually hardcoded to use http since my custom "js://" was passed to a BrowserHttpWebRequest.InternalBeginGetRequestStream as it's visible on the stacktrace :)
That confirms what Anthony had written - no way of having custom protocol handlers to work gracefully with the Silverlight's Browser Stack API.
However, I cannot agree with that the WebBrowser uses this connection factory. While is it true that the hidden factory is called BrowserHttp, and is true that it shares some per-user or per-session settings with the webbrowser, everything I try tens to indicate that the WebBrowser component uses yet completly other factory for its connections, and quite probably it is some native one. As an argument for that, I can only provide that I was able to successfully replace the original BrowserHttp factory with my simple custom implementation of it (both on the emulator and the phone), and with at least 6 webbrowsers in my current app, it wasn't used at all, not even once! (neither on the emulator, nor phone)

Persistent cookies in WPF WebBrowser control?

I'm using the WPF WebBrowser to display online help inside an app (just a few small web pages). Some of those pages use cookies to display items only for the first few times the pages are viewed (it's a "Why not try X" type of thing).
However, for some reason the cookies don't seem to be working inside the WebBrowser control. They work fine in full IE as well as Firefox and Chrome (so the items correctly hide), but they never hide when viewed through the WPF WebBrowser control.
Is there something special about using cookies in the WPF WebBrowser control? It seems to be behaving as if all the cookies are only stored in memory, rather than being persisted on disk.
Here's one of those pages inside a browser (where the cookies work):
And here's the exact same page inside the app:
That additional content should only be visible for the first few times of using the software (i.e. it should be hidden after N views of that web page), but because I can't get cookies to work it's always visible.
Cookies handling in Internet Explorer (or hosted versions) is tied to the IE's own notion of "URL Security Zones", doc here: About URL security Zones
So, IE determines an url zone using various alogorithms applied to the url. Depending on the zone, your hosted browser may or may not support session or persistent cookies.
Strangely, when I create a small WPF sample, add the web browser to it and have navigate to this persistent cookie tester utiliy page: http://www.rbaworld.com/Security/Computers/Cookies/givecook.shtml, it works fine. Each time I launch the sample app, the counter is incremented fine, so not everyone can reproduce your problem. Well, that's the whole purpose of URL Security zones: it can vary by machine, by user, by Windows policy, etc...
The next question is: Can I change the zone you're running in? The short and easy answer is ... no because it's heavily tied to the security.
If you were hosting IE yourself, you could implement your own security zone handle as described here: Implementing a Custom Security Manager and a sample here: SAMPLE: Secumgr.exe Overrides Security Manager for WebBrowser Host but you're relying on WPF's webbrowser that does not allow any override... You can get to Reflector and copy all WPF private/internal code but that's a log of risky work!
The last thing you can try is to manipulate the standard Internet Security Manager. Here is some sample code that gives some hints. At least you should be able to determine the zone you're running in (MapUrltoZone) and change the cookie (TryAllowCookie). The problem with the standard manager is most of the times, it pops up dialog to the end-user allowing authorization... (security again!):
[ComImport, Guid("7b8a2d94-0ac9-11d1-896c-00c04Fb6bfc4")]
private class InternetSecurityManager
{
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79eac9ee-baf9-11ce-8c82-00aa004ba90b")]
private interface IInternetSecurityManager
{
void Unused1();
void Unused2();
[PreserveSig]
int MapUrlToZone([In, MarshalAs(UnmanagedType.BStr)] string pwszUrl, out int pdwZone, [In] int dwFlags);
void Unused3();
[PreserveSig]
int ProcessUrlAction(string pwszUrl, int dwAction, ref int pPolicy, int cbPolicy, ref Guid pContext, int cbContext, int dwFlags, int dwReserved);
// left undefined
}
public static SecurityZone MapUrlToZone(Uri uri)
{
IInternetSecurityManager securityManager = (IInternetSecurityManager)new InternetSecurityManager();
int zoneId;
if (securityManager.MapUrlToZone(uri.ToString(), out zoneId, 0) < 0)
return SecurityZone.NoZone;
return (SecurityZone)zoneId;
}
private const int URLACTION_COOKIES = 0x00001A02;
private const int URLACTION_COOKIES_ENABLED = 0x00001A10;
private const int URLPOLICY_ALLOW = 0x00;
private const int URLPOLICY_DISALLOW = 0x03;
private const int PUAF_DEFAULT = 0x00000000;
public static bool TryAllowCookies(Uri uri)
{
IInternetSecurityManager securityManager = (IInternetSecurityManager)new InternetSecurityManager();
int policy = 0;
Guid context = Guid.Empty;
int hr = securityManager.ProcessUrlAction(uri.ToString(), URLACTION_COOKIES_ENABLED, ref policy, Marshal.SizeOf(policy), ref context, Marshal.SizeOf(context), PUAF_DEFAULT, 0);
return (hr == 0) && policy == URLPOLICY_ALLOW;
}
Good luck :)
The WebBrowser control won't allow this by default. For security reasons, you probably wouldn't want different applications from different developers/companies being able to access cookie info that another app created.
However, check out this answer How to delete Cookies from windows.form?
That pertains to deleting cookies through javascript, but you may be able to use a similar method in order to persist and create the site cookie each time the application is loaded.

Resources