I am trying to access a webpage through ASP.NET using the NetworkCredential class. However I keep getting an exception with the following message System.Security.Cryptography.CryptographicException: The handle is invalid
Below is my code on how I am trying to call the function. Any help is greatly appreciated.
C#:
System.Net.WebClient client = new System.Net.WebClient();
client.Credentials = new System.Net.NetworkCredential("Admin", "Nimda");
Stack Trace
[CryptographicException: The handle is invalid.
]
System.Security.SecureString.ProtectMemory() +154
System.Security.SecureString.InitializeSecureString(Char* value, Int32 length) +170
System.Security.SecureString..ctor(Char* value, Int32 length) +65
System.Net.SecureStringHelper.CreateSecureString(String plainString) +6181188
System.Net.NetworkCredential..ctor(String userName, String password) +64
I've just hit this same problem. I was happening locally under the ASP.NET Development Server in VS 2010. When I executed the app under my Windows 7 / IIS 7, it worked just fine. Hope this helps!
Ok this is a bit awkward - I've had a look and the error is down to your windows configuration .... somewhere.
The part of the code that's throwing an Exception is actually an interop call to a function in advapi32.dll, specifically:
int status = Win32Native.SystemFunction040(this.m_buffer, (uint) (this.m_buffer.Length * 2), 0);
if (status < 0)
{
throw new CryptographicException(Win32Native.LsaNtStatusToWinError(status));
}
this.m_encrypted = true;
Calls:
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
internal static extern int SystemFunction040([In, Out] SafeBSTRHandle pDataIn, [In] uint cbDataIn, [In] uint dwFlags);
That's returning an error code, causing your exception.
If you're in a workplace, you might want to talk with your sysadmin/network guys to see if there's anything in your local policies that might cause a failure.
Otherwise, I'd see what happens if you disable your Anti-virus/disable firewall/turn of any 3rd party proxy software.
Basically, anything that overrides default network functionality.
Also, might be worth checking you have all the latest windows updates and that you dont have any virus or malware infection.
Sorry I can't be more specific, but I don't believe this is a .Net/programming error.
This should work in a standard powershell console:
Add-Type -AssemblyName System.Net
$client = New-Object System.Net.WebClient
$netc = New-Object System.Net.NetworkCredential("Admin", "Nimda")
$client.Credentials = $netc
Will be interesting to see if this generates the same invalid handle error.
Edit: Apologies, there was a typo in the 2nd line.
Related
I am attempting to run a Native Code API (in a C++ .dll) via a C# assembly so that I can use certain API functions in a CLR Stored Procedure in SQL Server. The function that I am attempting to use from the C++ dll accesses raw data from a data historian and returns the data in unmanaged types. It is then left to the C# assembly to marshal and pipe results to the SQL Server.
I do not have the source code for the C++ dll, so I really do not know what exactly is going on underneath the hood (it is third-party). However, I can access these API functions in a C# console app without issue (I relied on https://lennilobel.wordpress.com/2014/01/29/calling-c-from-sql-clr-c-code/ for wrapping the C++ dll in .NET). I developed a working C# console app, then turned this into a Class Library, wrapped the class in "[Microsoft.SqlServer.Server.SqlProcedure]" and added the assembly to the desired SQL database in UNSAFE mode. I have also made sure that clr is enabled in the SQL server and TRUSTWORTHY is off in the database that I am using.
However, I get the following issue when I attempt to call the stored procedure that uses the C# assembly.
Location: AppDomain.cpp:2705
Expression: hr != E_POINTER
SPID: 66
Process ID: 3584
Msg 3624, Level 20, State 1, Procedure sp_direct_proficy_api, Line 0 [Batch Start Line 2]
A system assertion check has failed. Check the SQL Server error log for details. Typically, an assertion failure is caused by a software bug or data corruption. To check for database corruption, consider running DBCC CHECKDB. If you agreed to send dumps to Microsoft during setup, a mini dump will be sent to Microsoft. An update might be available from Microsoft in the latest Service Pack or in a Hotfix from Technical Support.
Msg 596, Level 21, State 1, Line 2
Cannot continue the execution because the session is in the kill state.
Msg 0, Level 20, State 0, Line 2
A severe error occurred on the current command. The results, if any, should be discarded.
I have done some google searches on system assertion checks and have seen that they usually occur as a result of database corruption. I have ran DBCC CHECKDB and everything looks fine, so this is not the issue. I have replicated Leonard's example (from the above link) that is essentially the same process that I am undertaking with a much simpler C++ dll. No errors occurred with that example, so I believe that there is some competition for an appdomain between SQL Server and the C++ API.
My Question
Is this an expected issue for what I am attempting to do? I don't know a whole lot about how SQL Server accesses computer memory and claims appdomains when using CLR Stored Procedures, but it seems as if there is some harmful resource competition between SQL Server and the C++ API.
Shown below are two parts of the C# assembly (the call to the C++ dll from the C# harness and the class to be accessed by the stored procedure).
C# DLL Import From C++
public class IHUAPI
{
const string DLLNAME = "IHUAPI.dll";
static class IHU64
{
[DllImport(DLLNAME, CallingConvention = CallingConvention.StdCall, EntryPoint = "ihuConnect#16")]
public static extern ihuErrorCode ihuConnect(string server, string username, string password, out int serverhandle);
[DllImport(DLLNAME, CallingConvention = CallingConvention.StdCall, EntryPoint = "ihuReadRawDataByTime")]
public static extern ihuErrorCode ihuReadRawDataByTime(int serverhandle, string tagname, ref IHU_TIMESTAMP start, ref IHU_TIMESTAMP end, out int numberOfSamples, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4, ArraySubType = UnmanagedType.LPStruct)] out IHU_DATA_SAMPLE[] samples);
}
public static ihuErrorCode ihuConnect(string server, string username, string password, out int serverhandle)
{
return IHU64.ihuConnect(server, username, password, out serverhandle);
}
public static ihuErrorCode ihuReadRawDataByTime(int serverhandle, string tagname, IHU_TIMESTAMP start, IHU_TIMESTAMP end, out IHU_DATA_SAMPLE[] samples)
{
int numberOfSamples;
return IHU64.ihuReadRawDataByTime(serverhandle, tagname, ref start, ref end, out numberOfSamples, out samples);
}
}
C# Assembly Used in Stored Procedure to Access C++ API
[Microsoft.SqlServer.Server.SqlProcedure]
public static void API_Query(string tagname, DateTime start_date, DateTime end_date)
{
int handle;
ihuErrorCode result;
result = IHUAPI.ihuConnect("houmseosprf007", "", "", out handle);
IHU_DATA_SAMPLE[] values;
IHU_TIMESTAMP start = new IHU_TIMESTAMP(start_date);
IHU_TIMESTAMP end = new IHU_TIMESTAMP(end_date);
ihuErrorCode result_api = IHUAPI.ihuReadRawDataByTime(handle, tagname, start, end, out values);
SqlMetaData[] md = new SqlMetaData[3];
md[0] = new SqlMetaData("tagname", SqlDbType.Text);
md[1] = new SqlMetaData("return_value", SqlDbType.NVarChar, 50);
md[2] = new SqlMetaData("timestamp", SqlDbType.DateTime);
SqlDataRecord row = new SqlDataRecord(md);
SqlContext.Pipe.SendResultsStart(row);
DateTime p;
string p2;
for (int i = 1; i < (values == null ? 0 : values.Length); i++)
{
using (IHU_DATA_SAMPLE sample = values[i])
{
if (sample.ValueDataType != ihuDataType.Array)
{
p = sample.TimeStamp.ToDateTime();
p2 = sample.ValueObject.ToString();
row.SetValue(0, tagname);
row.SetValue(1, p2);
row.SetValue(2, p);
}
else
{
p = sample.TimeStamp.ToDateTime();
ihuArrayValue aValue = (ihuArrayValue)Marshal.PtrToStructure(sample.Value.ArrayPtr, typeof(ihuArrayValue));
p2 = aValue.GetArrayValue.ToString();
row.SetValue(0, tagname);
row.SetValue(1, p2);
row.SetValue(2, p);
}
}
SqlContext.Pipe.SendResultsRow(row);
}
SqlContext.Pipe.SendResultsEnd();
}
Is this an expected issue for what I am attempting to do?
I wouldn't say "expected" so much as "not unexpected", or "shouldn't be surprised by". That 3rd party library is clearly doing something that is fine when it is isolated, but unacceptable when it is initiated from within SQL Server's CLR host. There is good reason for SQL Server's CLR host to be as highly restricted as it is.
So, what you should do instead is host this 3rd party C++ library and your original (and working) C# wrapper as a Web Service running on the server that hosts the service that you are connecting to, "IHU". Then, for your SQLCLR code, use HttpWebRequest and HttpWebResponse to call that web service. Parse the response XML / JSON in the SendResultsRow() loop.
Be sure to set the PERMISSION_SET of the updated SQLCLR code to be just EXTERNAL_ACCESS as you won't need UNSAFE :-) , and you still get fairly instantaneous response in your query batch without needing to shell out to call a command-line via xp_cmdshell or invoking SSIS or even scheduling a job to do it.
it seems as if there is some harmful resource competition between SQL Server and the C++ API.
Yes. You shouldn't really use unmanaged DLLs from SQL CLR. CLR managed code is memory-safe and SQLCLR is engineered to protect SQL Server from any issues arising from custom managed code. However if you use unmanaged code, you don't have any safety guarantees, and it's possible (likely) that you can crash SQL Server doing this.
Instead load the unmanaged DLL from a short-lived client process, separate from the SQL Server process, and short-lived so that any memory problems with the 3rd party DLL can get cleaned-up when the client process terminates. SSIS is simple way to host and run stuff like this.
We have supported different options in our product to download emails including IMAP and POP3. Providing IMAP and POP3 support was very simple as there is lot of documentation and .Net libraries available. Now we need to support MAPI.
I am having trouble with finding good library in .Net, I found one called NetMAPI but couldn't find examples. Also I am not able to understand how we specify connection properties. e.g. IMAP we have different properties like email address, password, port , SSL enabled etc. Below are few questions.
Where do I mention these connection parameters when it comes to
MAPI? ( creating profile? )
Some example says we have to mention profile name. Does that means I have to have outlook installed and create profile using outlook?
I am looking at this example but not sure how below Logon method is working on my machine.
[DllImport( "MAPI32.DLL", CharSet=CharSet.Ansi)]
private static extern int MAPILogon(IntPtr hwnd, string prf, string pw, int flg, int rsv, ref IntPtr sess );
public bool Logon( IntPtr hwnd )
{
winhandle = hwnd;
error = MAPILogon( hwnd, null, null, 0, 0, ref session );
if( error != 0 )
error = MAPILogon( hwnd, null, null, MapiLogonUI, 0, ref session );
return error == 0;
}
I am able to connect to my mailbox which is configured in outlook but don't know from where its picking up my mailbox details. I tried entering random ( invalid ) values for prf and pw fields still I am able to connect to my mailbox.
Strange but true.
Can someone please refer me to some good documentation to understand how to use MAPI ( preferably using managed API? )
Thanks
I've got a seemingly random "The handle is invalid" error when calling the following piece of code :
var properties = new Hashtable();
properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
properties.Add(MQC.HOST_NAME_PROPERTY, "MyHost");
properties.Add(MQC.PORT_PROPERTY, "MyPort");
properties.Add(MQC.CHANNEL_PROPERTY, "MyChannel");
this.QueueManager = new MQQueueManager("MyName", properties);
The environment is .NET Framework 3.5 & MQ Client 7.1
The problem is that this error doesn't occur repeatedly, maybe just 15% of the time, only in the production environment, and I can't seem to reproduce it within my development environment. The only trail I've got is that I know than it is possible for this code to be called simultaneously by two different processes. If it helps, I've also got the following stack trace :
Win32Exception - The handle is invalid
at System.Diagnostics.NtProcessManager.GetModuleInfos(Int32 processId, Boolean firstModuleOnly)
at System.Diagnostics.ProcessManager.GetModuleInfos(Int32 processId)
at System.Diagnostics.Process.get_Modules()
at IBM.WMQ.Nmqi.UnmanagedNmqiMQ.MQCONNX(String pQMgrName, MQCNO& pConnectOpts, Hconn parentHconn, Phconn phconn, Int32& pCompCode, Int32& pReason)
at IBM.WMQ.Nmqi.UnmanagedNmqiMQ.MQCONNX(String pQMgrName, MQConnectOptions pConnectOpts, Phconn phconn, Int32& pCompCode, Int32& pReason)
at IBM.WMQ.MQQueueManager.Connect(String queueManagerName)
at IBM.WMQ.MQQueueManager..ctor(String queueManagerName, Hashtable properties)
...
Any ideas ? Anyone ? :)
This fix might be of help to you. Have you downloaded the latest MQ Client for v7.1?
The code provided by Jon in the following thread seems to illustrate exactly what I want to do
Running a process at the Windows 7 Welcome Screen
Unfortunately it's in C#, a language I don't know at all. I'm trying to translate the code to Pascal (a recent version of Lazarus on Windows 7). From reading between the lines, I think I may have got a lot of it - however, I'll only know if I've got it wrong when it fails to do its job. At the moment it is failing to compile at the following point.
if (!DuplicateTokenEx(userToken, 0x10000000, ref tokenAttributes,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation,
out newToken)) {
log("ERROR: DuplicateTokenEx returned false - "
My Pascal version:
If Not DuplicateTokenEx(UserToken, MAXIMUM_ALLOWED, tokenAttributes,
SecurityImpersonation, TokenPrimary, newToken) then
Writeln(DLog, 'Failed to duplicate security token');
Lazarus throws an error on the fifth of the six parameters.
dmain.pas(189,110) Error: Incompatible type for arg no. 5: Got "TOKEN_TYPE", expected "_TOKEN_TYPE" - which indicates I haven't understood what the parameters are doing. (Changing parameter 5 to TokenImpersonation throws the same error.)
Further down, I get even more lost:
tokPrivs.Privileges = new LUID_AND_ATTRIBUTES[1];
tokPrivs.Privileges[0].Luid = seDebugNameValue;
tokPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
I can see that the structure type LUID_AND_ATTRIBUTES is in the Windows API but it seems it's not recognised by Lazarus.
In short, I'm groping around in the dark. I've tried Googling for "C# for Pascal programmers" but didn't find anything helpful. Learning C# isn't a trivial undertaking, so I be would really grateful for any hints on the differences between it and Object Pascal, and how to translate this code.
Edit: Unfinished code as requested.
function RunOurProcess(ProgramName: String): Boolean;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
NewToken, Token, UserToken: THandle;
WPID: DWord;
ThreadAttributes, TokenAttributes: TSecurityAttributes;
TOKPrivs: TTokenPrivileges;
begin
FillChar(StartInfo, SizeOf(TStartupInfo), #0);
FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
StartInfo.cb:= SizeOf(TStartupInfo);
{ Insert handle of current desktop - without this, GUI app is not visible!
To appear before logon, lpDesktop value should be 'winsta0\WinLogon' }
StartInfo.lpDesktop:= PChar('winsta0\WinLogon');
// Save the process ID of the WinLogon process
WPID:= FindInProcesses('Winlogon.exe');
// Get the handle of this
Token:= OpenProcess(TOKEN_QUERY or TOKEN_IMPERSONATE or TOKEN_DUPLICATE, False, WPID);
// Open a process token using the handle above
If OpenProcessToken(Token, TOKEN_QUERY or TOKEN_IMPERSONATE or TOKEN_DUPLICATE, UserToken) then
Writeln(DLog, 'Opened process token for WinLogon')
else
Writeln(DLog, 'Failed to open process token for WinLogon');
// Create a new token
NewToken:= 0;
tokenAttributes.nLength:= SizeOf(tokenAttributes);
threadAttributes.nLength:= SizeOf(threadAttributes);
If Not DuplicateTokenEx(UserToken, MAXIMUM_ALLOWED, tokenAttributes, SecurityImpersonation, TokenImpersonation, newToken) then
Writeln(DLog, 'Failed to duplicate security token');
// Elevate the privileges of the token
AdjustTokenPrivileges(NewToken, False, {NewState, BufferLength, PreviousState, ReturnLength});
// LogOnUser
// If successful, CreateProcessAsUser
// In progress - code below needs to go before 'CreateProcessAsUser'
StartInfo.cb:= SizeOf(TStartupInfo);
// Insert handle of current desktop - without this, GUI app is not visible!
StartInfo.lpDesktop:= PChar('winsta0\WinLogon');
end; // RunOurProcess
I notice now that I get the following error if I try to find the declaration for "DuplicateTokenEx"
C:\lazarus\fpc\2.6.1\source\packages\winunits-jedi\src\jwawindows.pas(366,5) Error: include file not found "JwaLmErr.pp"
Here's how to solve the compilation problems.
The call to DuplicateTokenEx actually fails on the third parameter. Looking at the declaration, it is LPSECURITY_ATTRIBUTES which is ^TSecurityAttributes. Now, tokenAttributes is of type TSecurityAttributes so you need to pass its address:
If Not DuplicateTokenEx(..., #tokenAttributes, ...) then
And similarly in the call to AdjustTokenPrivileges. The C# code is:
AdjustTokenPrivileges(newToken, false, ref tokPrivs, 0, IntPtr.Zero, IntPtr.Zero)
Translated to Pascal that would be:
AdjustTokenPrivileges(NewToken, False, #TOKPrivs, 0, nil, nil)
I've no idea whether or not the code will solve your problem. I think that's beyond the remit of this question – at least that's my excuse and I'm sticking to it!
I have an ASP.NET web application that stores a HTTP cookie when a certain action has been performed (e.g. a link has been clicked). Now, I am creating a standalone C# app which needs to watch the cookies folder and recognise when a cookie entry has been created by my web application and read the contents of the cookie.
Could anyone please guide me on how to do this in C# or show sample code?
I can't help thinking that is simply the wrong way to do it... and it reaks of security abuse. Is there no better way you could do this? Perhaps hosting the page in a WebBrowser control and using an ObjectForScripting object (of your devising) so you can talk to the C# app from javascript?
You should be able to PInvoke InternetGetCookie.
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
protected static extern bool InternetGetCookie(
string url,
string name,
StringBuilder cookieData,
ref int length);
You can then call InternetGetCookie like below assuming you are using the Rest Starter Kit.
StringBuilder cookieBuffer = new StringBuilder(1024);
int size = 1024;
bool bSuccess = InternetGetCookie("domain uri", "cookie_name", cookieBuffer, ref size);
if (!bSuccess)
{
Int32 err = Marshal.GetLastWin32Error();
//log err
}
if (cookieBuffer != null && (cookieBuffer.Length > 0))
{
Microsoft.Http.Headers.Cookie cookie = Microsoft.Http.Headers.Cookie.Parse(cookieBuffer.ToString());
HeaderValues<Microsoft.Http.Headers.Cookie> requestCookies = new HeaderValues<Microsoft.Http.Headers.Cookie>();
requestCookies.Add(cookie);
}
There is another thing you can do that could cause your local application to be invoked by the clicking of a link. You'd need to register an application to a URL protocol as seen here. Here is a tutorial and sample app you can look at.
Doing this has it's own set of security implications. However, it is an easy way to invoke your application from the web page and it allows you to pass data via command line params.