Search content within the blog

Tuesday, April 19, 2011

Impersonate user to access network resources

This class can be used to perform impersonation of a user over the network and can be used to access resources that are shared.

copy paste the following class in a file,
public class NetworkSecurity
{
const string USER_NAME = "Imperson_FileShare_Username";
const string PASSWORD = "Imperson_FileShare_Password";
const string LOGON_TYPE = "Imperson_logon_Type";
const string LOGONPROVIDER = "Imperson_logon_Provider";

NetworkSecurity()
{
}

public static WindowsImpersonationContext GetWindowsImpersonationContext()
{
try
{
WindowsImpersonationContext impersonatedUser = null;
LogonType logonType = LogonType.LOGON32_LOGON_NETWORK;
LogonProvider logonProvider = LogonProvider.LOGON32_PROVIDER_DEFAULT;


string loginUserName = VestekAppSettings.GetInstance().GetSetting(USER_NAME, true);
string loginPassword = VestekAppSettings.GetInstance().GetSetting(PASSWORD, true);

string domainName = null;
if (loginUserName.Length > 0)
{
string[] splitteddomainAndUserName = loginUserName.Split('\\');
if (splitteddomainAndUserName.Length.Equals(2))
{
domainName = splitteddomainAndUserName[0];
loginUserName = splitteddomainAndUserName[1];
}

}
impersonatedUser = ImpersonateUser(domainName, loginUserName, loginPassword, logonType, logonProvider);
return impersonatedUser;
}
catch (Exception ex)
{
throw ex;
}
}


private static WindowsImpersonationContext ImpersonateUser(string strDomain,
string strLogin,
string strPwd,
LogonType logonType,
LogonProvider logonProvider)
{
IntPtr tokenHandle = new IntPtr(0);
IntPtr dupeTokenHandle = new IntPtr(0);
WindowsImpersonationContext impersonatedUser = null;

try
{
const int SecurityImpersonation = 2;

tokenHandle = IntPtr.Zero;
dupeTokenHandle = IntPtr.Zero;

// Call LogonUser to obtain a handle to an access token.
bool returnValue = SecuUtil32.LogonUser(
strLogin,
strDomain,
strPwd,
(int)logonType,
(int)logonProvider,
ref tokenHandle);
if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
string strErr = String.Format("LogonUser failed with error code : {0}", ret);
throw new ApplicationException(strErr, null);
}

bool retVal = SecuUtil32.DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle);
if (false == retVal)
{
SecuUtil32.CloseHandle(tokenHandle);
throw new ApplicationException("Failed to duplicate token", null);
}

// The token that is passed to the following constructor must
// be a primary token in order to use it for impersonation.
WindowsIdentity newId = new WindowsIdentity(dupeTokenHandle);
impersonatedUser = newId.Impersonate();


}
catch (Exception ex)
{
throw new ApplicationException(ex.Message, ex);
}

return impersonatedUser;
}

enum LogonType : int
{
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK = 3,
LOGON32_LOGON_BATCH = 4,
LOGON32_LOGON_SERVICE = 5,
LOGON32_LOGON_UNLOCK = 7,
LOGON32_LOGON_NETWORK_CLEARTEXT = 8, // Only for Win2K or higher
LOGON32_LOGON_NEW_CREDENTIALS = 9 // Only for Win2K or higher
};

enum LogonProvider : int
{
LOGON32_PROVIDER_DEFAULT = 0,
LOGON32_PROVIDER_WINNT35 = 1,
LOGON32_PROVIDER_WINNT40 = 2,
LOGON32_PROVIDER_WINNT50 = 3
};

class SecuUtil32
{
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr TokenHandle);

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
}

}




Now in order to access a resource over a network by a particular user we can call this class in the following way,

try
{
WindowsImpersonationContext impContext = null;
if (impContext == null)
impContext = NetworkSecurity.GetWindowsImpersonationContext();


if (impContext == null)
{
string msg = "Access denied : Error occured while accessing the file over the network.\n";
sLogger.Error("Could not create the impersonation object.");
throw new VestekException(msg);
}

---write code here to access network resource
}
catch (Exception error)
{
throw error;
}
finally
{
//check if the object was created and is not null
if (impContext != null)
impContext.Undo();
}

now if the impContext is not null that means the user was impersonated successfully. So continue to access and run the code under this user. Once the opreration is complete maintain a finally block where you would call impContext.Undo();.

Sunday, April 10, 2011

Foreground or Background Thread

Types of Threads
Basically, there are two types of threads which fall into:

* Foreground Thread
* Background Thread

# Foreground threads have the ability to prevent the current application from terminating. The CLR will not shut down an application (which is to say, unload the hosting AppDomain) until all foreground threads have ended.

# Background threads (sometimes called daemon threads) are viewed by the CLR as expendable paths of execution that can be ignored at any point in time (even if they are currently laboring over some unit of work). Thus, if all foreground threads have terminated, any and all background threads are automatically killed when the application domain unloads.

It is important to note that foreground and background threads are not synonymous with primary and worker threads. By default, every thread you create via the Thread.Start() method is automatically a foreground thread. Again, this means that the AppDomain will not unload until all threads of execution have completed their units of work. In most cases, this is exactly the behavior you require.

Example:
Create a windows application with two buttons.Foreground and background threads....
add the following code for them

private void button1_Click(object sender, EventArgs e)
{
// Creates a background thread
ThreadStart threadStart = new ThreadStart(TenSecondsMethod);
Thread backgroundThread = new Thread(threadStart);
backgroundThread.IsBackground = true;
backgroundThread.Start();

MessageBox.Show("A method of 25 seconds delay is invoked!" + Environment.NewLine + "Now try closing the application and check Task Manager > Processes.");
}

private void TenSecondsMethod()
{
// Method of 25 seconds delay
Thread.Sleep(25000);
}

private void button2_Click(object sender, EventArgs e)
{
// Creates a foreground thread
ThreadStart threadStart = new ThreadStart(TenSecondsMethod);
Thread foregroundThread = new Thread(threadStart);
foregroundThread.IsBackground = false;
foregroundThread.Start();

MessageBox.Show("A method of 25 seconds delay is invoked!" + Environment.NewLine + "Now try closing the application and check Task Manager > Processes.");
}

After clicking each button, you can try closing the application.

From the windows task manager we can see the application would not be listed in the case of Background thread created.

From the windows task manager we can see the application would be still running in the case of Foreground thread created.

The following image shows the snapshot of task manager just after closing the application after invoking a foreground thread.


Garbage collector in C#

The .NET garbage collector is known as generational garbage collector. The objects allocated are categorized into three generations. Most recently allocated objects are placed in generation 0.
Objects in generation 0, that survive a garbage collection pass are moved to generation 1.
generation 2 contains long-lived objects, that survive after the two collection passes.

A garbage collection pass for generation 0 is the most common type of collection. Generation 1 collection pass is performed if generation 0 collection pass is not sufficient to reclaim memory.
Atlast, generation 2 collection pass is peformed if collection pass on generation 0 and 1 are not sufficient to reclaim memory. If no memory is available, after all the collection passes, an
OutOfMemoryException is thrown.

Dispose
public void Dispose()
{
// all clean up source code here..
GC.SuppressFinalize(this);
}

It is advisable to place these calls in a finally clause, which guarantees that the objects are properly handled even if an exception is thrown.

When you exit the program, you can make the System.GC methods force the GC to schedule the implicit finalizer call, and then wait for that call to complete, as shown.

System.GC.Collect();
System.GC.WaitForPendingFinalizers();

You can also call System.GC.SuppressFinalize to prevent the garbage collector from implicitly invoking the finalizer a second time.

Do not directly call your base class Finalize method. It is called automatically from your destructor.

Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose, if available.

To explicitly destroy the object, you should call System.GC.SuppressFinalize immediately to prevent multiple object deallocation by the GC:

System.GC.SuppressFinalize(anyInstance);

// example: explicit destruction/finalize
using System;

class MyClass : IDisposable
{
public MyClass() //default ctor
{
this.iNumber = 0;
System.Console.WriteLine("ctor:MyClass {0}", iNumber);
}

public MyClass(Int32 iNumber) // specialized ctor
{
this.iNumber = iNumber;
System.Console.WriteLine("ctor:MyClass {0}", iNumber);
}

~MyClass() // dtor or finalize
{
System.Console.WriteLine("dtor:~MyClass {0}", iNumber);
}

public void Dispose() // helper finalize function
{
// here you can free the resources you allocated explicitly
System.GC.SuppressFinalize(this);
}

private int iNumber;
}

class main
{
static void Main()
{
MyClass myClass1 = new MyClass();
MyClass myClass2 = new MyClass(19);
myClass1.Dispose(); // myClass1 is explicitly exposed.
System.GC.Collect();
System.GC.WaitForPendingFinalizers();

// myClass2 is implicitly exposed by GC.
Console.ReadLine();
}
}



using System;

namespace GCCollect
{
class Account
{
public Account(string accountNumber)
{
this.accountNumber = accountNumber;
Console.WriteLine("Account::Acount - c'tor");
}
~Account()
{
Console.WriteLine("Account::~Acount - d'tor");
}

protected string accountNumber;
override public string ToString() { return accountNumber; }
};

class Class1
{
[STAThread]
static void Main(string[] args)
{
CreateAccount("111006116");

GC.Collect();
GC.WaitForPendingFinalizers();

Console.WriteLine("Application ending");
}

public static void CreateAccount(string accountNumber)
{
Console.WriteLine("CreateAccount - instantiate Account object");
Account account = new Account(accountNumber);
Console.WriteLine("CreateAccount - created account number {0}",
account);
}
}
}


Note a couple of issues here:

1. I allocated the Account object in a different method than the Main method. This is because if I allocated the Account object in the Main method and then called GC.Collect in the same method, the Account object would technically still be associated with running code and would therefore not be eligible for collection.
2. While I used a simple single object example here to illustrate calling the GC.Collect method, the GC.Collect method is designed not to control specific object destruction, but to allow for the forcing of collection for all of unused objects. Therefore, it's a very expensive operation and should only be used in cases where you want/need to force global collection.
3. For situations where you want to force the finalization of a specific object, you should implement the Dispose pattern, which I'll cover in a separate article.