Sunday, 19 April 2009
Two events and a PG course
1.) Great Indian Developer Summit : Happening on days April 22, 23, 24 appears to be the place to be for any software engineer in the .NET/Web/Java streams. Look forward for talks on upcoming cutting edge technologies.
2.) Like to meet geeky innovators who have taken the turn with their startups ? This is the place to be on June 6th
3.) Would like to pick up an MS in Computer Science by attending a weekend programme ? Check out the 2 year MS Computer Science course for professionals conducted by Christ University.
Friday, 17 April 2009
DES Uploaded to CodePlex
Check the homepage at http://des.codeplex.com/ for a brief summary of the project.
Tuesday, 24 March 2009
Boxed & Secured Execution Of a .NET Type
One of the usual needs in an application developers world is to instantiate a .NET type in a boxed/contained/isolated environment with zero impact to the current application process space. How do we do that? This article solves this in an easy manner, adoptable easily.
Usual Solution
The immediate answer is to use an Application Domain - create new application domain and instantiate the type within the new domain. Sounds straight forward. Sadly nope. If you thought the following lines of code would just work, you are mistaken. To reconfirm that it does not work, try unloading the app domain and then deleting the loaded assembly from the windows explorer. It does not let you delete the assembly file. What happened here?
//create the application domain and create an instance of the object
AppDomain clientDomain = AppDomain.CreateDomain("ClientTaskDomain");
Object executionObject = clientDomain.CreateInstanceAndUnwrap("ABC.Test", "MyTest");
//find the Execute method and call it.
MethodInfo executionMethod = executionObject.GetType().GetMethod("Execute");
returnData = executionMethod.Invoke(executionObject, null);
As the type ABC.Test.MyTest was not a MarshalByRefObject descendant, the type instance gets loaded into the main application domain. Instead if the type ABC.Test.MyTest did descend from MarshalByRefObject, the type would have been instantiated in the 'remote' application domain. Thats the way it is designed.
Easy Way Out
Have a proxy type created in your application which descendants from MarshalByRefObject. Instantiate this object and call a proxy routine on this proxy object which then instantiates the real type. In this way, as the proxy type is already created in the new application domain, the real type too would be created in the new application domain.
AppDomain clientDomain = AppDomain.CreateDomain("ClientTaskDomain");
try
{
AssemblyLoader _aLoader = (AssemblyLoader)clientDomain.CreateInstanceAndUnwrap("XYZ.Test", "XYZ.Test.AssemblyLoader");
returnData = _aLoader.LoadAndRun("ABC.Test", "MyTest");
}
finally
{
AppDomain.Unload(clientDomain);
}
where AssemblyLoader is defined as an MBR descendant as :
[Serializable]
public class AssemblyLoader : MarshalByRefObject
{
public Object Execute(string assemblyName, string typeName)
{
Assembly _assembly = Assembly.Load(assemblyName);
Type _type =_assembly.GetType(typeName);
MethodInfo _method =_type.GetMethod("Execute");
return _method.Invoke(Activator.CreateInstance(_type), null);
}
}
Using this method, we have made sure that "MyTest" is always instantiated in the new application domain.
Impersonate for Security
All good until now, but how do you make sure the executed code executes under a user supplied account ? Pretty simple if you know how to authenticate a username/password/domain. Sadly, there is no direct way to perform a windows authentication in .NET. Not sure why there isnt a "bool WindowsPrincipal.Authenticate(userName, passWord,domain)" routine ? No clues. We could go the LogonUser route, but it appears it has certain permission issues in NT/2000 basedmachines. Hence, lets write one using the NegotiateStream
public static class SSPIHelper
{
enum AuthenticationState { Unknown, Success, Failure } ;
public static WindowsPrincipal LogonUser(NetworkCredential credential)
{
string userName, domain, password;
userName = credential.UserName;
domain = credential.Domain;
password = credential.Password;
TcpListener tcpListener = new TcpListener(IPAddress.Loopback, 0);
tcpListener.Start();
WindowsIdentity id = null;
AuthenticationState authState = AuthenticationState.Unknown;
IAsyncResult serverResult = tcpListener.BeginAcceptTcpClient(delegate(IAsyncResult asyncResult)
{
using (NegotiateStream serverSide = new NegotiateStream(
tcpListener.EndAcceptTcpClient(asyncResult).GetStream()))
{
try
{
serverSide.AuthenticateAsServer(CredentialCache.DefaultNetworkCredentials,
ProtectionLevel.None, TokenImpersonationLevel.Impersonation);
id = (WindowsIdentity)serverSide.RemoteIdentity;
authState = AuthenticationState.Success;
}
catch (Exception e)
{
authState = AuthenticationState.Failure;
}
}
}, null);
using (NegotiateStream clientSide = new NegotiateStream(new TcpClient("localhost",
((IPEndPoint)tcpListener.LocalEndpoint).Port).GetStream()))
{
try
{
clientSide.AuthenticateAsClient(new NetworkCredential(userName, password, domain),
"", ProtectionLevel.None, TokenImpersonationLevel.Impersonation);
authState = AuthenticationState.Success;
}
catch (Exception E)
{
authState = AuthenticationState.Failure;
}
}
while (authState == AuthenticationState.Unknown) ;
tcpListener.Stop();
if (authState == AuthenticationState.Success)
return new WindowsPrincipal(id);
else
return null;
}
}
Ok, we have a windows principal. Now what ? Impersonate to execute the code using this principal, which happens to be the easy bit.
WindowsIdentity newId = (WindowsIdentity)windowsPrincipal.Identity; //the one received from SSPIHelper
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
This makes sure that the code following the above Impersonate() call uses the provided identity. Once we want to revert back to the original identity, just do a Undo() (see below)
So effectively what we now have is an isolated and safe execution of a type provided by the client using the credentials supplied by them. To summarize, the code should look similar to this:
//authenticate the client supplied credentials
WindowsPrincipal windowsPrincipal = SSPIHelper.LogonUser(credentials);
WindowsIdentity newId = (WindowsIdentity)windowsPrincipal.Identity;
//impersonate
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
try
{
//create the application domain and create an instance of the object
AppDomain clientDomain = AppDomain.CreateDomain("ClientTaskDomain");
try
{
//use the proxy MBR object
AssemblyLoader _aLoader = (AssemblyLoader)clientDomain.CreateInstanceAndUnwrap("XYZ.Test", "XYZ.Test.AssemblyLoader");
returnData = _aLoader.LoadAndRun("ABC.Test", "MyTest");//call the client's method
}
finally
{
AppDomain.Unload(clientDomain);
}
}
finally
{
impersonatedUser.Undo();//back to the normal a/c
File.Delete(assemblySaveLocation);//just to clean up things, clean the client's assembly too.
}
Thursday, 16 October 2008
Chrome crashed
In fact I thought Chrome would never crash when one of the tab got screwed since there was this concept of each tab executing within a different process. A behaviour easily verified by browsing to about:memory and cross checking the PID with the windows process ID.
Sunday, 12 October 2008
WCF Service and a SilverLight 2 beta 2 Application
Sunday, 9 March 2008
Bounce that spam please!
The only issues we might face:
1.) This involves the mix-up of user-requirement with the underlying protocol!. No purists would like this.
2.) The spam-generators would start getting intelligent in sending spams - It might start using different 'from' addresses and messages against the same Inbox. If either of the email was delivered, it can safely assume that the email-id is valid. This could be resolved by letting the email-server perform auto-bounce using the same logic it uses currently for spam, rather than explicitly marking it for an 'auto-bounce'.
3.) In cases of the server automatically handling it, we might loose a couple of good emails since it was identified as spam and got auto-bounced.
Can this work ? How else can I avoid that spam from reaching my email box and avoid skimming through the hundreds of spam in search of that one good-email ?
Wednesday, 5 March 2008
Injections
Dependency Injection refers to the process by which functional components ('concerns' in AOP terms) are induced into an object such that the object could use its functionalities. Say, you had a Customer Management module and one of the function it does was audit the name of all users who updated a customer record. On the simplest terms, we might have the following classes :
MyBusinessObject - A base class for each the business entity classes.
Customer - The business entity containing the customer details - name, DOB, Address etc. This being derived from MyBusinessObject.
CustomerManager - Manages all business functions related with the customer. Say, adding customer, deleting, searching, modifying etc
MySimpleAudit - A class which does the audit the various operations.
In simplest case, CustomerManager class would directly instanstiate the MySimpleAudit class and call the appropriate Audit function. All good. If we have more Audit classes , say StackTraceAudit (which audits the stack trace too..why? I dont know), ObjectStreamAudit (Audits the current state of the object) , the standard design logic would call for interfaces to separate the functionality out, in our case perhaps into an IAudit interface.
IAudit
AuditDelete(MyBusinessObject)
AuditCreate(MyBusinessObject)
AuditModify(MyBusinessObject)
We would then make sure that all our Audit classes (MySimpleAudit, StackTraceAudit, ObjectStreamAudit) implement this interface. The only confused class is the CustomerManager class which does not know which IAudit implementing class to use. Ofcourse it could depend on a configuration entry to get the audit class name or it could just hard-code to use one of the class etc.
What if we could tell directly to the CustomerManager which audit object to use ? The crux of dependency injection is this . Injecting an object (IAudit Instance) instance into another object (CustomerManager) such that the injectee (the object that got injected! sic indeed) can use the functionality of the injected object (IAudit instance).
You could pass the instance of the injected object in three standard ways as part of the constructor , use a property or use an interface definition.
For our customer example, passing the object via a constuctor would be in the lines of :
class CustomerManager
{
private _audit IAudit;
CustomerManager (audit IAudit)...
DeleteCustomer(Customer customer)
{
_audit.AuditDelete(customer as MyBusinessObject)
}
}
In this case, when the CustomerManager class is instantiated, the right audit instance is passed along - eg :- new CustomerManager(new StackTraceAudit)
Stuff noted:
1.) CustomerManager is not disturbed for any changes/additions to the IAudit implementation
2.) Any new IAudit implementation class can be created without affecting the consuming class.
3.) What is depicted is effectively an 'Inversion of Control'. The control of locating, creating of the audit class being inverted to a different object.
4.) This pattern decouples the logic of - which object, from where etc out from the consumer object.
Policy Injection
For the similar scenario as above, assume you had a single Audit object consumed by CustomerManager. Now if there is a new requirement to include the functionalities of StackTrace, ObjectLogging too into the audit system, what would you do?
Though there are numerous immediate solutions to get the stuff working (modify existing Audit class to call the other audits as well, create yet another master class which calls all the audit objects etc), Policy Injection calls for creating a proxy object class for the currently available Audit class. It would be this proxy class which gets used by at the CustomerManager object instead of the Audit object.
The CustomerManager object might end up using a Factory pattern or a dependency injection pattern (!) to get the right proxy audit class (reread this line again till it makes sense.)
Now interestingly, what the Audit proxy object class would perform is this:
1.) On the way in (when the request for audit happened) , it would call the 'Pre' step routines of all registered audit handlers (StackTrace, ObjectStream etc) in a sequence and finally call the original Audit class routines.
2.) On the way back (when the request for audit is done), it might call further 'Post' step routines on each of the handlers in the reverse order.
As seen, from the point of view of the CustomerManager, it is dealing with only one object, which is the new Audit proxy object. Whenever it calls the proxy Audit class to audit, all the handlers would perform its audit (either in the pre/post routines) and finally call the original Audit object.