I want to Access External resources inside the CLR Code... But I am getting Security Exception
I have marked Assembly with External Access... here is the way I am doing..
I read articles and MSDN .. everywhere is written to use impersonation like
using (WindowsIdentity id = SqlContext.WindowsIdentity)
{
WindowsImpersonationContext c = id.Impersonate();
//perform operations with external resources and then undo
c.Undo();
}
In above case .. I tried both Windows Authentications and SQL Authentications ...
In case of Windows.. I am have a domain login to logon to my pc, while sql server is at another machine and Active directory is at different machine .. when connect to Database .. it says cannot find user Domainname\user
and the SqlContext.WindowsIdentity is always null or it has exception User.Toked thew Security exception.
After that .. I tried to user custome Identity .. using IIdentity =GenericIdentity("UserName","Windows");
But there is now difference .. still same exception .. as given below..
[Microsoft.SqlServer.Server.SqlProcedure]
public static void MyProcedure()
{
Process[] p = Process.GetProcessesByName("YPager"); //Yahoo messanger exe .. a process
p[0].kill();
}
A .NET Framework error occurred during execution of user defined routine or aggregate 'MyProcedure': System.Security.SecurityException: Request failed.
System.Security.SecurityException:
at System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Assembly asm, PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission permThatFailed)
at System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Object assemblyOrString, PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission permThatFailed)
at System.Security.CodeAccessSecurityEngine.CheckSetHelper(PermissionSet grants, PermissionSet refused, PermissionSet demands, RuntimeMethodHandle rmh, Object assemblyOrString, SecurityAction action, Boolean throwException)
at System.Security.CodeAccessSecurityEngine.CheckSetHelper(CompressedStack cs, PermissionSet grants, PermissionSet refused, PermissionSet demands, RuntimeMethodHandle rmh, Assembly asm, SecurityAction action)
at DatFileGenerator.StoredProcedures.'MyProcedure'()
.
No rows affected.
(0 row(s) returned)
@.RETURN_VALUE =
Finished running [dbo].['MyProcedure'].
How could I go ahead... what I should do to accompilsh the task...
Kindlly .. suggestions and ideas..
Thanks,
Muna
few things that might help you...
first, there is this blog post, http://blogs.msdn.com/dataaccess/archive/2006/01/25/517495.aspx
second, YOU MUST CONNECT TO DATABASE USING WINDOWS AUTHENTICATION FOR IMPERSONATION TO WORK
third, try using the UNSAFE PERMISSION SET instead of external access
fourth, here is an impersonation sample from my upcoming SQLCLR book:
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure()]
public static void uspExternalConnection()
{
WindowsIdentity newIdentity = null;
WindowsImpersonationContext newContext = null;
try
{
//impersonate the caller
newIdentity = SqlContext.WindowsIdentity;
newContext = newIdentity.Impersonate();
if (newContext != null)
{
using (SqlConnection oConn =
new SqlConnection("Server=.\\sqlexpress;" +
"Integrated Security=true;"))
{
SqlCommand oCmd = new SqlCommand("SELECT * FROM " +
"AdventureWorks.HumanResources.Employee", oConn);
oConn.Open();
SqlDataReader oRead =
oCmd.ExecuteReader(CommandBehavior.CloseConnection);
//revent security context
newContext.Undo();
//return results
SqlContext.Pipe.Send(oRead);
}
}
else
{
throw new Exception("user impersonation has failed");
}
}
catch (SqlException ex)
{
SqlContext.Pipe.Send(ex.Message.ToString());
}
finally
{
if (newContext != null)
{
newContext.Undo();
}
}
}
};
|||
Hi Muna,
It looks like your impersonation call and attempt to access external resources are working - the problem is with what you're trying to done from an external_access assembly. Finding and killing an external process is not allowed in external_access assemblies, so you'll need to use UNSAFE instead. The exception shows that you're hitting a CodeAccessSecurity violation, as stated in the clr documentation on the Process class: http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.aspx
"This class contains a link demand and an inheritance demand at the class level that applies to all members. A SecurityException is thrown when either the immediate caller or the derived class does not have full-trust permission. For details about security demands, see Link Demands and Inheritance Demands."
Steven
|||
Thank you for the for helping me out ....
I am able to connect to database, inserting, updating and pulling out data from there, using Windows Authentication....
As well .. I have written data to a file (on filesystem)
All it work fine But when I try to use the code to kill a process .. It generate Exception
Here is code which cause Exception....
public partial class StoredProcedures
{
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure()]
public static void TestSecurity()
{
WindowsIdentity newIdentity = null;
WindowsImpersonationContext newContext = null;
try
{
//impersonate the caller
newIdentity = SqlContext.WindowsIdentity;
newContext = newIdentity.Impersonate();
if (newContext != null)
{
using (SqlConnection oConn = new SqlConnection(@."Data Source=MyComputerName\SQLEXPRESS;Initial Catalog=DataBaseName;Integrated Security=True;"))
{
SqlCommand oCmd = new SqlCommand("SELECT * FROM " +"AdventureWorks.HumanResources.Employee", oConn);
oConn.Open();
SqlDataReader oRead = oCmd.ExecuteReader(CommandBehavior.CloseConnection);
Process[] p = Process.GetProcessesByName("YPager"); //Yahoo messanger exe .
p[0].kill();
//revent security context
newContext.Undo();
//return results
SqlContext.Pipe.Send(oRead);
}
}
else
{
throw new Exception("user impersonation has failed");
}
}
catch (SqlException ex)
{
SqlContext.Pipe.Send(ex.Message.ToString());
}
finally
{
if (newContext != null)
{
newContext.Undo();
}
}
}
}
};
The Problem is with killing external (windows) process from SQL App
SQL Server AppDomain
About impersonating the user.... I am getting Exception
//impersonate the caller
during debuggin At this line when I check in wach window
newIdentity = SqlContext.WindowsIdentity;
It has following information....
AuthenticationType = 'SqlContext.WindowsIdentity.AuthenticationType' threw an exception of type 'System.UnauthorizedAccessException'
Groups = {System.Security.Principal.IdentityReferenceCollection}
ImpersonationLevel = Impersonation
IsAnonymous = false
IsAuthenticated = true
IsGuest = false
IsSystem=false
Name="DomainName\myLoginName"
Owner = {S-1-5-21-15454545467-37684546461-44646464642-1176}
Token="2342"
User = {S-1-5-21-1878703567-3768572861-466091742-1176}
hmmmm Where I am going wrong?
|||Hi Steven,
Thank you for helping me out...
I have used the attribute as following..
[assembly: IsolatedStorageFilePermission(SecurityAction.RequestMinimum, UsageAllowed = IsolatedStorageContainment.AssemblyIsolationByUser)]
public partial class
StoredProcedures
{
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure()]
public static void TestSecurity()
{
WindowsIdentity newIdentity = null;
WindowsImpersonationContext
newContext = null;
try
{
//impersonate the caller
newIdentity =
SqlContext.WindowsIdentity;
newContext =
newIdentity.Impersonate();
if (newContext !=
null)
{
using (SqlConnection oConn = new
SqlConnection(@."Data Source=MyComputerName\SQLEXPRESS;Initial
Catalog=DataBaseName;Integrated Security=True;"))
{
SqlCommand oCmd = new
SqlCommand("SELECT * FROM " +"AdventureWorks.HumanResources.Employee",
oConn);
oConn.Open();
SqlDataReader oRead =
oCmd.ExecuteReader(CommandBehavior.CloseConnection);
Process[] p = Process.GetProcessesByName("YPager");
//Yahoo messanger exe .
p[0].kill();
//revent security
context
newContext.Undo();
//return results
SqlContext.Pipe.Send(oRead);
}
}
else
{
throw new
Exception("user impersonation has failed");
}
}
catch (SqlException ex)
{
SqlContext.Pipe.Send(ex.Message.ToString());
}
finally
{
if (newContext !=
null)
{
newContext.Undo();
}
}
}
}
};
It is helping me out to kill the process
but still exception 
ExitCode = 'p[0].ExitCode' threw an exception of type 'System.InvalidOperationException'
Thanks
|||
Have you tried killing YPager and doing p[0].ExitCode outside SQL Server in a simple console app? The documentation on Process.ExitCode (http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.exitcode.aspx) says the following:
Exceptions
Exception type
Condition
InvalidOperationException
The process has not exited.
-or-
The process Handle is not valid.
If it works outside SQL Server. Can you post the complete exception that you are getting from inside SQL?
Thanks,
-Vineet.
|||Hi Vineet,
For better understanding here are some facts
ComputerName = ProductionPC
Application Name = TestApplication
Here is execution .code..
Auto-attach to process '[3224] [SQL] ProductionPC' on machine 'ProductionPC' succeeded.
Running [dbo].[TestSecurity].
The thread 'ProductionPC\sqlexpress [55]' (0x8a0) has exited with code 0 (0x0).
The thread 'ProductionPC\sqlexpress [55]' (0x8a0) has exited with code 0 (0x0).
The thread 'ProductionPC\sqlexpress [55]' (0x8a0) has exited with code 0 (0x0).
'sqlservr.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'sqlservr.exe' (Managed): Loaded 'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn\SqlAccess.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'sqlservr.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Data.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'sqlservr.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'sqlservr.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_32\System.Transactions\2.0.0.0__b77a5c561934e089\System.Transactions.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'sqlservr.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System.Security\2.0.0.0__b03f5f7f11d50a3a\System.Security.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Auto-attach to process '[3224] sqlservr.exe' on machine 'ProductionPC' succeeded.
'sqlservr.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c561934e089\System.Xml.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'sqlservr.exe' (Managed): Loaded 'TestApplication', Symbols loaded.
'sqlservr.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System.Configuration\2.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll', No symbols loaded.
EmployeeID NationalIDNumber ContactID LoginID ManagerID Title BirthDate MaritalStatus Gender HireDate SalariedFlag VacationHours SickLeaveHours CurrentFlag rowguid ModifiedDate
-- - -- - -- -- -- - -- - -- -- -- --
No rows affected.
(1 row(s) returned)
@.RETURN_VALUE =
Finished running [dbo].[TestSecurity].
The thread 'ProductionPC\sqlexpress [55]' (0x8a0) has exited with code 0 (0x0).
The program '[3224] [SQL] ProductionPC: ProductionPC\sqlexpress' has exited with code 0 (0x0).
The program '[3224] sqlservr.exe: Managed' has exited with code 259 (0x103).
Taking look on object P (instance holding the process to kill ) in watch window.. gives following iformation
- p {Dimensions:[1]} System.Diagnostics.Process[]
- [0] {System.Diagnostics.Process (DAP)} System.Diagnostics.Process
+ base {System.Diagnostics.Process (DAP)} System.ComponentModel.Component {System.Diagnostics.Process}
BasePriority 8 int
EnableRaisingEvents false bool
+ ExitCode 'p[0].ExitCode' threw an exception of type 'System.InvalidOperationException' int {System.InvalidOperationException}
+ ExitTime 'p[0].ExitTime' threw an exception of type 'System.InvalidOperationException' System.DateTime {System.InvalidOperationException}
+ Handle 3524 System.IntPtr
HandleCount 439 int
HasExited false bool
Id 2576 int
MachineName "." string
+ MainModule {System.Diagnostics.ProcessModule (DAP.exe)} System.Diagnostics.ProcessModule
+ MainWindowHandle 0 System.IntPtr
MainWindowTitle "" string
+ MaxWorkingSet 1413120 System.IntPtr
+ MinWorkingSet 204800 System.IntPtr
+ Modules {System.Diagnostics.ProcessModuleCollection} System.Diagnostics.ProcessModuleCollection
NonpagedSystemMemorySize 30440 int
NonpagedSystemMemorySize64 30440 long
PagedMemorySize 16273408 int
PagedMemorySize64 16273408 long
PagedSystemMemorySize 75080 int
PagedSystemMemorySize64 75080 long
PeakPagedMemorySize 37670912 int
PeakPagedMemorySize64 37670912 long
PeakVirtualMemorySize 132988928 int
PeakVirtualMemorySize64 132988928 long
PeakWorkingSet 22728704 int
PeakWorkingSet64 22728704 long
PriorityBoostEnabled true bool
PriorityClass Normal System.Diagnostics.ProcessPriorityClass
PrivateMemorySize 16273408 int
PrivateMemorySize64 16273408 long
+ PrivilegedProcessorTime {00:00:00.8437500} System.TimeSpan
ProcessName "DAP" string
+ ProcessorAffinity 1 System.IntPtr
Responding true bool
SessionId 0 int
+ StandardError 'p[0].StandardError' threw an exception of type 'System.InvalidOperationException' System.IO.StreamReader {System.InvalidOperationException}
+ StandardInput 'p[0].StandardInput' threw an exception of type 'System.InvalidOperationException' System.IO.StreamWriter {System.InvalidOperationException}
+ StandardOutput 'p[0].StandardOutput' threw an exception of type 'System.InvalidOperationException' System.IO.StreamReader {System.InvalidOperationException}
+ StartInfo {System.Diagnostics.ProcessStartInfo} System.Diagnostics.ProcessStartInfo
+ StartTime {7/28/2006 11:14:44 PM} System.DateTime
SynchronizingObject null System.ComponentModel.ISynchronizeInvoke
+ Threads {System.Diagnostics.ProcessThreadCollection} System.Diagnostics.ProcessThreadCollection
+ TotalProcessorTime {00:00:03.7031250} System.TimeSpan
+ UserProcessorTime {00:00:02.8593750} System.TimeSpan
VirtualMemorySize 132988928 int
VirtualMemorySize64 132988928 long
WorkingSet 9736192 int
WorkingSet64 9736192 long
+ Static members
+ Non-Public members
Thanks|||
Muna & Steve,
I marked steve's reply as correct...(which he was correct, much better than my response)...NOW HOW CAN I MARK A REPLY AS AN ANSWER TO A THREAD I DID NOT START LOL!
|||Hi
Derek
Thank you for your comments...
I am really glad to know that you are very generous in addition to be a developer (Engineer /Manager)
You are right that steve's reply is more helping...and I will mark it too..
But I am having few exceptions as posted above... I want to make it working so that some one else can get somplete solution from here too..
I will wornder if you guys could help me out to resolve these exceptions related issues.
Thanks
|||
Hi,
Try this:
Process[] p = Process.GetProcessesByName("YahooMessenger"); //Yahoo messanger exe .
p[0].EnableRaisingEvents = true;
p[0].Kill();
p[0].WaitForExit();
int ExitCode = p[0].ExitCode;
This is explained in the documentation for Process.ExitCode at http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.exitcode.aspx . I think i had a link to this documentation in my previous post as well :)
Thanks,
-Vineet.
|||
Hi Vineet,
I could not take a look on your last reply ..(on weekend went away ...)
As you refere to your previous post's links... yes, I worked on that .. as well as on the suggestions from other friends...
Till right now What I got is ..
1- I have marked assembly Unsafe, It allow to kill the process ,
when I call the SP from Visual Studio... even there are exceptions .. but still process if killed
2 - when same SP is called from SQL server, exception is thrown, I am using integrated connection...
Msg 6522, Level 16, State 1, Procedure TestSecurity, Line 0
A .NET Framework error occurred during execution of user defined routine or aggregate 'TestSecurity':
System.ComponentModel.Win32Exception: Access is denied
System.ComponentModel.Win32Exception:
at System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited)
at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited)
at System.Diagnostics.Process.OpenProcessHandle()
at System.Diagnostics.Process.set_EnableRaisingEvents(Boolean value)
at StoredProcedures.TestSecurity()
Because, the actual problem has not been resolved thats why I have not marked any answer.
Any alternate path to accomplish this task?
Thanks,
|||
Hi,
The code i have posted above worked just fine for me (registering the assembly as unsafe). My setup is Windows XP SP2, SQL Server 2005, Yahoo Messenger 7.5.0.819. I am using Windows authentication and my machine is on a domain. I am admin on the machine as well as on SQL Server. SQL Server is running under Local System.
Could you please post your complete code that throws this exception. Also provide details on your setup. It looks like the account you are running under does not have sufficient privileges to open the process. If you search on the internet you would find posts like http://www.thescripts.com/forum/thread162942.html that provide some explanation and suggestions.
Thanks,
-Vineet.
|||
Hi Vineet,
I have just changed the login on account for sqlservice.exe from domain to local system.. now even I am loged on to pc with a domain login.. I am able to impersonate the user.. It is working fine ..
The actual problem was in impersonation...
the Sqlserver was running under network service acount while I was loged using domain user login..
secondly, at start I was using external_access while now with Unsafe..
At the end .. I am able to kill a process, start a process from stored procedure..(SQLCLR SP)
I am closing this thread now..
Thank you all friends for replies.