|
SAO - Activator.GetObject().
CAO - Activator.CreateInstance().
Config File - new
|
|
|
|
|
Windows applications in VS.NET use the name app.config by default for the configuration file. This will not be automatically created when you create a Windows application. If you need a configuration file for your application, open your project in VS.NET, go to the 'Solution Explorer' and right click on the project name. Choose Add > Add new item from the menu and select 'Application Configuration file' from the list of choices. This will create an app.config file for you in the application root.
When you compile your application, VS.NET will automatically create a file called <your application name>.exe.config in your bin\debug folder. The contents of the app.config will be automatically copied to this new config file when you compile the application. When you deliver the application to the end user, you have to deliver the exe and this new config file called <your application name>.exe.config and NOT the app.config. Users can modify the data in <your application name>.exe.config file and application will read the data from the config file, when restarted.
|
|
|
|
|
Remember that the config file -must- be named app.config and nothing else !
|
|
|
|
|
1. Make sure your depencency DLL is compiled with a strong name. This is because you will need to reference the Public Key Token in the client application's config file.
2. Create a file directory in your local hard disk in which to store your DLL (e.g. c:\MyLib). Store your dependency DLL there, e.g. c:\MyLib\MyLib.dll
3. Web Shard this folder. This will cause IIS to register a Virtual Directory for your Web Shared folder.
4. In your client application config file, supply a config file with at least the following data :
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity
name="MyLib"
publicKeyToken="f165dd82fa9f2434"
culture="neutral"
/>
<codeBase version="1.0.0.0"
href="http://localhost/MyLib/MyLib.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
5. Go to the .NET Configuration Tool and create a new Code Group. For this new Code Group, under Membership Condition, select "URL" for the condition type.
6. For the URL, type in the web path to your dependency assembly : e.g. :
"http://localhost/MyLib/MyLib.dll" or "http://localhost/MyLib/*"
7. If you happen to change anything (especially method signatures) in your dependency DLL, be sure to refresh the local cache of used assemblies by deleting the appropriate insance of your DLL in the following directory :
<documents and settings folder>\<user id>\local settings\application data\assembly\dl2.
Otherwise, your old dependency DLL will still be cached and used.
|
|
|
|
|
In addition, by including the use of the FileIOPermissionAttribute class, we can ensure that subsequent code will read ONLY specified file(s) and will write to ONLY specified file(s), e.g. :
[FileIOPermissionAttribute(SecurityAction.PermitOnly, Read="C:\\security.txt", Write="C:\\security.out.txt")]
private void buttonReadFile_Click(object sender, System.EventArgs e)
{
SecureFileReader sfr = new SecureFileReader();
byte[] byDataIn = sfr.ReadFile("c:\\security.txt");
Stream fs_out = new FileStream("c:\\security.out.txt", FileMode.Create,
FileAccess.Write);
fs_out.Write(byDataIn, 0, byDataIn.Length);
fs_out.Close();
}
The desired effect is achieved even if unrestricted FileIOPermission to the file system has been granted for the assembly.
|
|
|
|
|
byte[] byData = SomeFunctionThatReturnsAByteArray();
string MyString = System.Text.UnicodeEncoding.Unicode.GetString(byData);
|
|
|
|
|
At the .NET Command Line Prompt, type :
"mscorcfg.msc"
|
|
|
|
|
byte[] byData = System.Text.UnicodeEncoding.Unicode.GetBytes(strMyString);
|
|
|
|
|
If you need to open a file (for reading only) in IIS for your ASP.NET application, be sure to use the FileAccess.Read flag in your FileStream constructor, e.g. :
FileStream fs = new FileStream
(
m_strServerPath + sbBinFileName.ToString(),
FileMode.Open,
FileAccess.Read // <-- important.
);
Otherwise, the file access attempt may fail.
|
|
|
|
|
If you use a StringBuilder object over and over again, you may need to reset its values before attempting to re-assign values to it via AppendFormat :
In this case, use the Remove() method, e.g. :
sb_string.Remove(0, sb_string.Length);
sb_string.AppendFormat(@"...", ...);
|
|
|
|
|
Initialization code :
using System.Security.Principal;
using System.Reflection;
using System.Security.Permissions;
using System.Threading;
using System.Security;
...
...
...
private enum role
{
OPERATIONAL = 0,
ADMIN = 1,
MANAGER = 2
};
private static string[] m_strAvailableRoles = new string[] { "OPERATIONAL", "ADMIN", "MANAGER" };
private static GenericIdentity m_generic_identity;
private static GenericPrincipal m_generic_principal;
...
...
...
string[] m_strCurrentRoles = new string[]
{ m_strAvailableRoles[(int)role.ADMIN] };
// Initialize the identity and principal objects used in this application.
InitializeIdentityAndPrincipal("john", m_strCurrentRoles);
// Initialize the entire application according to the values set in the
// current identity and principal objects.
InitializeApplicationAccordingToCurrentIdentityAndPrincipal();
...
...
...
// Create and initialize the identity and principal objects used in this
// application.
// We will use Reflection to create objects.
protected void InitializeIdentityAndPrincipal
(string strUserName, string[] strCurrentRoles)
{
Type[] type_array = new Type [] { typeof(string) };
object[] object_array = new object[] { strUserName };
ConstructorInfo ci = typeof(GenericIdentity).GetConstructor(type_array);
// Create a GenericIdentity object by invoking the GenericIdentity
// constructor that takes in a single string value (i.e. the name of the
// user on whose behalf the code is running).
m_generic_identity = (GenericIdentity)(ci.Invoke(object_array));
// Re-use type_array and object_array.
type_array = new Type [] { typeof(GenericIdentity), typeof(string[]) };
object_array = new object[] { m_generic_identity, strCurrentRoles };
ci = typeof(GenericPrincipal).GetConstructor(type_array);
// Create a GenericPrincipal object by invoking the GenericPrincipal
// constructor that takes in a GenericIdentity object and a string array of
// roles.
m_generic_principal = (GenericPrincipal)(ci.Invoke(object_array));
}
// Initialize the entire application according to the values set in the
// current identity and principal objects.
protected void InitializeApplicationAccordingToCurrentIdentityAndPrincipal()
{
// Set the current thread's current principal (for role-based security).
Thread.CurrentPrincipal = m_generic_principal;
// Enable and disable the menu items in the application according to
// the role of the current principal.
if (m_generic_principal.IsInRole(m_strAvailableRoles[(int)
role.OPERATIONAL]))
{
operationsItem.Enabled = true;
}
else
{
operationsItem.Enabled = false;
}
...
...
...
}
|
|
|
|
|
PrincipalPermission Demands :
// We use declarative PrincipalPermission demands on the current thread.
// Here, we are stating that any person with OPERATIONAL and MANAGER
// roles may perform OperationsAction().
// However, ONLY a person named "janet" with ADMIN role may perform
// OperationsAction().
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="OPERATIONAL")]
[PrincipalPermissionAttribute(SecurityAction.Demand, Name="janet", Role="ADMIN")]
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="MANAGER")]
private void OperationsAction()
{
Message("Operations Action");
}
// We use declarative PrincipalPermission demands on the current thread.
// Here, we are stating that any person with ADMIN and MANAGER
// roles may perform OperationsAction().
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="ADMIN")]
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="MANAGER")]
private void AdminAction()
{
Message("Admin Action");
}
private void ManagerAction()
{
// We use imperative PrincipalPermission demand to ensure that
// only "john", "paul", "george" and "ringo" (all having ADMIN role)
// can perform important action in this function.
PrincipalPermission principal_permission_john = new PrincipalPermission("john", m_strAvailableRoles[(int)role.MANAGER]);
PrincipalPermission principal_permission_paul = new PrincipalPermission("paul", m_strAvailableRoles[(int)role.MANAGER]);
PrincipalPermission principal_permission_george = new PrincipalPermission("george", m_strAvailableRoles[(int)role.MANAGER]);
PrincipalPermission principal_permission_ringo = new PrincipalPermission("ringo", m_strAvailableRoles[(int)role.MANAGER]);
try
{
principal_permission_john.Union(principal_permission_paul.Union(principal_permission_george.Union(principal_permission_ringo))).Demand();
Message("Manager Action");
}
catch (SecurityException se)
{
Message("Security Exception : " + se.Message);
}
}
|
|
|
|
|
In order to combine the use of SymmetricAlgorithm and AsymmetricAlgorithm for key exchange purposes, it seems that the key and block sizes must each be 256.
Otherwise, we get a "System.Security.Cryptography.CryptographicException" with additional info : "PKCS7 padding is invalid and cannot be removed."
|
|
|
|
|
In addition, if you were to use the CryptoStream object to perform Symmetric Encryption, e.g. :
public static void Encrypt_SymmetricAlgorithm_File
(
ref Stream stream_in,
ref Stream stream_out,
ref SymmetricAlgorithm sa
)
{
CryptoStream c = new CryptoStream
(
stream_out,
sa.CreateEncryptor(),
CryptoStreamMode.Write
);
byte [] buf = new byte[BUFSIZE];
int siz;
while ((siz = stream_in.Read(buf,0, BUFSIZE)) > 0)
c.Write(buf, 0, siz);
c.Close(); // This better be called.
return;
}
You better call the CryptoStream.Close() method. Otherwise, the cryptographic output to the output stream ("stream_out" in the above example), may become corrupted.
|
|
|
|
|
Also, it would be good programming practice to call CryptoStream.Close() when you use the CryptoStream for dercyption, e.g. :
public static void Decrypt_SymmetricAlgorithm_File
(
ref Stream stream_in,
ref Stream stream_out,
ref SymmetricAlgorithm sa
)
{
CryptoStream c = new CryptoStream
(
stream_in,
sa.CreateDecryptor(),
CryptoStreamMode.Read
);
byte [] buf = new byte[BUFSIZE];
int siz;
while ((siz = c.Read(buf,0, BUFSIZE)) > 0)
stream_out.Write(buf, 0, siz);
c.Close(); // This better be called.
}
|
|
|
|
|
The Close() ensures that padding is correctly performed. Without it, the stream is likely to be corrupted.
|
|
|
|
|
1. Suppose that you have created a string out of a DateTime object e.g. :
string strDateTime = DateTime.Now.ToShortDateString();
2. To later convert this DateTime string back to its original DateTime object, use the Parse() method together with DateTimeFormatInfo.CurrentInfo :
DateTime dt = DateTime.Parse(strDateTime, DateTimeFormatInfo.CurrentInfo);
3. CurrentInfo is a property of DateTimeFormatInfo which returns a read-only DateTimeFormatInfo object that formats values based on the current culture.
4. Note that because "strDateTime" was formatted according to the current culture, we can use DateTimeFormatInfo.CurrentInfo to retrieve -that- culture.
|
|
|
|
|
|