Encrypting Files using DPAPI

In one of my current projects (yes, there are more at the moment and yes that is the reason why it's a bit quiet around here) i neede to write an encrypted file to the hard disc using DPAPI (Data Protection API). After I unsuccessfully searched the web and the msdn (the sample reads all bytes to the buffer at once - not so nice), I wrote the following sample app: using System; using System.IO; using System.Security.Cryptography;   public class DataProtectionSample {     public static void Main()     {         using(MemoryStream ms = new MemoryStream())         {             StreamWriter swriter = new StreamWriter(ms);             swriter.WriteLine("Text to encrypt to file.");             swriter.Flush();               Console.WriteLine("Protecting data ...");             DataProtection.Protect("D:\\_temp\\DPAPI.dat", ms, false);         }         Console.WriteLine("Unprotecting data ...");         using(MemoryStream ms2 =             (MemoryStream)DataProtection.Unprotect("D:\\_temp\\DPAPI.dat", false))        {             StreamReader sreader = new StreamReader(ms2);             Console.WriteLine("");             Console.WriteLine("Decrypted string: " + sreader.ReadToEnd());         }         Console.ReadLine();     } }   public class DataProtection {     private static byte[] _additionalEntropy = { 9, 8, 7, 6, 5 };     private static int _bufferLength = 1024;       public static void Protect(string filename, Stream stream,         bool machineLevel)     {         if (File.Exists(filename))         {             File.Delete(filename);         }         using (FileStream fs = new FileStream(filename, FileMode.CreateNew))         {             byte[] buffer = new byte[_bufferLength];             long byteCount;             stream.Position = 0;             while ((byteCount =                stream.Read(buffer, 0, buffer.Length)) > 0)             {                 buffer = ProtectedData.Protect(buffer, _additionalEntropy,                     ((machineLevel) ? DataProtectionScope.LocalMachine :                     DataProtectionScope.CurrentUser));                 fs.Write(buffer, 0, buffer.Length);                 fs.Flush();             }         }     }       public static Stream Unprotect(string filename, bool machineLevel)     {         MemoryStream ms = new MemoryStream();                 using (FileStream fs = new FileStream(filename, FileMode.Open))         {             byte[] buffer = new byte[_bufferLength + 146];             long byteCount;               while ((byteCount =                fs.Read(buffer, 0, buffer.Length)) > 0)             {                 buffer = ProtectedData.Unprotect(buffer, _additionalEntropy,                     ((machineLevel) ? DataProtectionScope.LocalMachine :                     DataProtectionScope.CurrentUser));                 ms.Write(buffer, 0, buffer.Length);                 ms.Flush();             }         }         ms.Position = 0;         return ms;     } }      

Executing CREATE statements from within Visual Studio 2005

If you try to run a CREATE statement in a query (right click on a database in the Server Explorer) you receive this message. So i wrote a small utility which will do the job for me. using System; using System.IO; using System.Data.SqlClient; using System.Collections.Generic; using System.Text; using System.Windows.Forms;   namespace MdfExec {     class Program     {         static void Main(string[] args)         {             string _cnStr;               if (args.Length == 2)             {                 _cnStr =                     "data source=.\\SQLEXPRESS;Integrated Security=SSPI;" +                     "AttachDBFilename=" + args[1] + ";User Instance=true;";             }             else             {                 OpenFileDialog fd = new OpenFileDialog();                   fd.AddExtension = true;                 fd.DefaultExt = ".mdf";                 fd.ShowDialog();                   _cnStr =                     "data source=.\\SQLEXPRESS;Integrated Security=SSPI;" +                     "AttachDBFilename=" + fd.FileName + ";User Instance=true;";             }               using (SqlConnection _cn = new SqlConnection(_cnStr))             {             using(SqlCommand _cmd = _cn.CreateCommand())                    {                     using (StreamReader fs = File.OpenText(args[0]))                     {                         _cmd.CommandText = fs.ReadToEnd();                         _cmd.Connection.Open();                         _cmd.ExecuteNonQuery();                     }                    }             }         }     } }   You can now right click on a *.sql file choose "open with ..." and select MdfExec.exe to execute the SQL statement. Since there is no second parameter (but needed to define to which database to connect) a OpenFileDialog will prompt:   Happy coding

Customizing the Prop Snippet

I'm quite busy with a project I'm on with Clemens (the last before he'll join the Indigo team at Microsoft) - just to explain why it got bit quiet around me :-) Here is a modified version of the prop snippet that I want to share ( and remember :-P ). <?xml version="1.0" encoding="utf-8" ?> <CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">       <CodeSnippet Format="1.0.0">             <Header>                   <Title>prop</Title>                   <Shortcut>prop</Shortcut>                   <Description>Code snippet for property and                   backing field</Description>                   <Author>Microsoft Corporation</Author>                   <SnippetTypes>                         <SnippetType>Expansion</SnippetType>                   </SnippetTypes>             </Header>             <Snippet>                   <Declarations>                         <Literal>                              <ID>type</ID>                               <ToolTip>Property type</ToolTip>                              <Default>int</Default>                         </Literal>                         <Literal>                              <ID>property</ID>                              <ToolTip>Property name</ToolTip>                              <Default>MyProperty</Default>                         </Literal>                         <Literal>                              <ID>field</ID>                              <ToolTip>The variable backing this                              property</ToolTip>                              <Default>myVar</Default>                         </Literal>                   </Declarations>                   <Code Language="csharp"><![CDATA[#region $property$             // This field holds the $property$       private $type$ $field$;         /// <summary>Gets/sets the $property$.</summary>       /// <value>A <see cref="$type$">$type$</see>       /// containing the $property$.</value>       /// <remarks>This property gets/sets the $property$.</remarks>       [System.ComponentModel.Description("Gets/sets the $property$.")]       public $type$ $property$       {             get { return $field$;}             set { $field$ = value;}       }       #endregion       $end$]]>                   </Code>             </Snippet>       </CodeSnippet> </CodeSnippets>

Cool Tool: Cassini here power toy

[...]The .NET Framework 2.0 comes with a built-in webserver, based on the old Cassini web server. So I wanted to be able to easily set up any directory to have its contents served up on an as-needed basis. The result is an addition to the Windows Explorer right-click menu...[Robert McLaws] Chris Fraizer wrote it thgether in a small app. Here is my version with a few modifications: using System; using System.IO; using System.Collections.Generic; using System.Diagnostics; using System.Windows.Forms; using System.Text; using System.Runtime.InteropServices;   namespace WebServerHere {     class Program     {         static void Main(string[] args)         {             if (args.Length >= 1)             {                 string _path;                   string _command =                     Path.Combine(                     RuntimeEnvironment.GetRuntimeDirectory(),                     "WebDev.WebServer.EXE");                   StringBuilder _commandArgs = new StringBuilder();                   Random _r = new Random();                   string _port = _r.Next(1024, 9000).ToString();                   if (args.Length == 2)                 {                     _port = args[1];                 }                     //grab the original path                 _path = args[0];                   _commandArgs.Append(" /path:\"");                 _commandArgs.Append(_path);                 _commandArgs.Append("\"");                 _commandArgs.Append(" /port:");                 _commandArgs.Append(_port);                 _commandArgs.Append(" /vpath: \"/");                 _commandArgs.Append(_path.Substring(                     _path.LastIndexOf('\\') + 1));                 _commandArgs.Append("\"");                   ProcessStartInfo _info =                     new ProcessStartInfo();                   _info.Arguments = _commandArgs.ToString();                 _info.CreateNoWindow = true;                 _info.FileName = _command;                 _info.UseShellExecute = false;                 _info.WorkingDirectory =                     _command.Substring(0, _command.LastIndexOf('\\'));                     Process.Start(_info);                   using (Control _c = new Control())                 {                     Help.ShowHelp(_c, "http://localhost:" + _port + "/");                 }             }             else             {                 MessageBox.Show("Usage:\n\tWebServerHere.exe <path> [port]",                     "WebServerHere", MessageBoxButtons.OK,                     MessageBoxIcon.Information);             }         }     } } And the Non-Admin installation reg-file: Windows Registry Editor Version 5.00 [HKEY_Current_User\SOFTWARE\Classes\Folder\shell\VS2005 WebServer]@="ASP.NET 2.0 Web Server Here" [HKEY_Current_User\SOFTWARE\Classes\Folder\shell\VS2005 WebServer\command]@="\"%SystemRoot%\\System32\\WebServerHere.exe\" %1"

A week full of community

Monday: I met Andreas Hoffmann (2nd UG Lead of the VfL Usergrop) and Peter Nowak (Head of FIAEon.net, a community for .NET related vocational education) at Starbucks in Düsseldorf. Tuesday: Benjamin Mitchell notified me that one of my sessions was voted by the british community and I'll have a session at the Developer Developer Developer Day. Wednesday: I'm in contact with the Student Partners in Wuppertal now (better said Anselm Haselhoff because Marcel Wiktorin is moving and has not replied yet :-)). Thursday: Usergroup meeting in Düsseldorf: Sebastian Weber (Developer Evengelist at Microsoft Germany and member of the VfL-UG) answered all our members questions about SQL Server 2005 and Tuan Nguyen (Lead of annos.de and VfL-Member) talked about the Annos project. Great, thanks guys. Friday: I updated the VfL-Site and fixed a few bugs.

Don't mess with sharepoint...

Carefully said I do not like that sharepoint "hijacks" the Internet Information Server. When you create a virtual directory it is just not accessable because SharePoint took over IIS. Funny fact: This is the second post how to fix issues with IIS and "extension" that cause issues :-) So i decided to hack a small utility serving my needs: ExcludeFromSharepoint.zip (3.46 KB) Enables to exclude applications from sharepoint services through the directory context menu. Install using the "-install" switch; Uninstall using "-uninstall" switch. Because I'm running my machine under a LUA (Limited User Account) i wrote the tool in a way that you can install and uninstall it without administative rights - the contextmenu will be installed per user! if(args[0]=="-install") {     RegistryKey _rkey = Registry.CurrentUser;     _rkey = _rkey.OpenSubKey("SOFTWARE\\Classes",true);     _rkey = _rkey.CreateSubKey("Folder").CreateSubKey("shell");     _rkey = _rkey.CreateSubKey("Exclude from Sharepoint");     _rkey = _rkey.CreateSubKey("command");     _rkey.SetValue(null, App.Application.ExecutablePath + " \"%1\""); } else if(args[0]=="-uninstall") {     RegistryKey _rkey = Registry.CurrentUser;     _rkey = _rkey.OpenSubKey("SOFTWARE\\Classes\\Folder\\shell",true);     _rkey.DeleteSubKeyTree("Exclude from Sharepoint"); } else { ... }   The Implementation works with the webserver extensions version 4.0 or higher       RegistryKey _rkey = Registry.LocalMachine;     _rkey = _rkey.OpenSubKey("SOFTWARE\\Microsoft\\Shared Tools\\" +         "Web Server Extensions",true);         foreach(string _subKeyName in _rkey.GetSubKeyNames())     {         try         {             int.Parse(_subKeyName.Replace(".",""));             RegistryKey _fpKey = _rkey.OpenSubKey(_subKeyName,true);             _fpDir = (string)_fpKey.GetValue("Location");         }         catch(Exception _ex)         {             string _err = _ex.ToString();             break;         }     }   and uses the stsadm.exe from the shared tools of the server extensions.     System.Diagnostics.Process _p = new System.Diagnostics.Process();     _p.StartInfo.FileName = Path.Combine(_fpDir, "BIN\\stsadm.exe");     _p.StartInfo.Arguments = "-o addpath -url http://localhost/" +         _strProjectName + " -type exclusion";     ...     _p.Start();  

RE: httpOnly cookies in ASP.NET 1.1

Scott posted a solution to support httpOnly cookies in ASP.NET 1.1 but pointed out some problems when you run the code on 2.0(http://www.hanselman.com/blog/HttpOnlyCookiesOnASPNET11.aspx) Here is a solution: protected void Application_EndRequest(Object sender, EventArgs e) { if(System.Environment.Version.Major<2) { foreach(string cookie in Response.Cookies) { const string HTTPONLY = ";HttpOnly"; string path = Response.Cookies[cookie].Path; if (path.EndsWith(HTTPONLY) == false) { //force HttpOnly to be added to the cookie Response.Cookies[cookie].Path += HTTPONLY; } } } }

Re: Windows Impersonation in ASP.NET

Pierre posted an entry bout impersonation in ASP.NET szenarios. [Pierre]There are several scenario where you have to use the impersonation in ASP.NET. Consider, for example, you have to save and load files from a network share (file server). In that case, if the web site accept anonymous authentications, you have to impersonate a windows user who has enought privileges to access to that resource. You have three choices (I guess): Elevate the ASP.NET process identity - worse case since you could compromise the whole site security Impersonate a windows user during the single call (http://blogs.msdn.com/shawnfa/archive/2005/03/22/400749.aspx) Demand the task to a COM+ server application I think that the last is the best since we have more security and maintenance control[...] I agree with him that "Demand the task to a COM+ server application" is the best way of the three he listed. But for me impersonation it is still a don't. By the way i wanted to post this as a comment but "Comments on this post are closed". Yes this is some criticism on weblogs.asp.net :-) ... So here my opinion as post in my blog: Avoid impersonation! If you need to "redirect a binary that is located on a different box than the webserver to the client" utilize another IIS on the 2nd machine or write a service that returns the binary data.  

Using IFused with the FCKEditor

Miroslaw Maslyk has sent this small tutorial on how to use iFused with the FCKEditor. Thank you very much Miro ;-) 1. Rename file FCKeditor\editor\dialog\fck_image.html to fck_image.aspx. 2. On the top this file (fck_image.aspx) add this code: <%@ Page Language="C#" %><%@ Register TagPrefix="Uploader"  namespace="StaticDust.Web.UI.Controls"  assembly="StaticDust.Web.UI.Controls.UploadDialog" %><script runat="server">protected void Page_Load(Object source, EventArgs e) {    StaticDust.Web.UI.Controls.UploadDialogButton _u =      new StaticDust.Web.UI.Controls.UploadDialogButton();    _u.UploadDirectory = "~/images";    _u.ReturnFunction = "SetUrl()";    btnBrowse.Attributes["OnClick"] =      "javascript:" + _u.JavascriptLink; } </script> 3. Find btnBrowse input html tag , add runat="server" attribute and close tag (/>) 4. Replace in files FCKEditor\FCKeditor\editor\js\fckeditorcode_ie_2.js and fckeditorcode_gecko_2.js all fck_image.html sentence to fck_image.aspx