May 2012 Blog Posts

A couple of years ago I posted my solution for the infamous “A potentially dangerous Request.Form value was detected from the client” error when using TinyMCE with ASP.NET 4.0.

The solution worked (mostly) without turning off request validation.

Since then, I’ve changed my approach slightly; I’ve dropped the Moxiecode TinyMCE ASP.NET assembly and have gone with a purely JavaScript solution. I think it works better, and it’s a lot cleaner and more up to date.

There are a few parts to this:

  1. Implementing TinyMCE JavaScript version
  2. Decoding HTML server-side on POST
  3. Handling TinyMCE re-encoding HTML on Postback

Implementing TinyMCE JavaScript version

Download TinyMCE (just grab the main package, which “contains all you need for production usage”), extract and copy the files into your solution.

Any page that has a TinyMCE text editor will need to include the base js file and a chunk of initialization script to set up all our options.

<script type="text/javascript" src="/_assets/tiny_mce/tiny_mce.js"></script>

<script type="text/javascript" >
    tinyMCE.init({
        mode: "specific_textareas",
        editor_selector: "tinymce",
        encoding: "xml",
        convert_urls: false,
        theme: "advanced",
        plugins: "spellchecker,pagebreak,style,layer,table,advhr,advimage,advlink,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,paste,directionality,fullscreen,visualchars,nonbreaking,xhtmlxtras",
        extended_valid_elements: "iframe[src|width|height|name|align]",
        theme_advanced_buttons1: "spellchecker,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect,|,print,fullscreen",
        theme_advanced_buttons2: "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
        theme_advanced_buttons3: "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,media,advhr,|",
        theme_advanced_toolbar_location: "top",
        theme_advanced_toolbar_align: "left",
        theme_advanced_path_location: "bottom",
        theme_advanced_resizing: true,
        theme_advanced_resize_horizontal: false,
        theme_advanced_styles: "Link to Image: lightbox;Image Right Border: rightbordered;Image Left Border: leftbordered;Darker Text: darker",
        setup: function (ed) {
            ed.onSaveContent.add(function (i, o) {
                o.content = o.content.replace(/&#39/g, "&apos");
            });
        }
    });
</script>

I’ve got all my site-specific configuration in the plugins and themes options; you’ll probably want to change those for your implementation.

There are three key areas here you want to pay attention to.

mode: "specific_textareas",
editor_selector: "tinymce",

These two tell TinyMCE to only initialize textareas with a class attribute containing “tinymce”. That means we won’t accidentally create TinyMCE instances if we’re using other textareas on the page.

encoding: "xml",

The encoding option (off by default) tells TinyMCE to XML-encode all HTML in our textarea on POST. This is critical for ASP.NET.

setup: function (ed) {
    ed.onSaveContent.add(function (i, o) {
        o.content = o.content.replace(/&#39/g, "&apos");
    });
}

Apostrophes will give you a lot of grief unless you explicitly add this onSaveContent() handler to convert them to a safe, encoded string. This is critical for ASP.NET.

Now all we have to do is include a textarea with the right class, and the init() function will take care of setting up TinyMCE for us.

<textarea
    id="htmlBody"
    runat="server"
    class="tinymce"
    rows="40"
    cols="120" />

Easy!

Decode HTML server-side on POST

Because TinyMCE is encoding HTML, we might choose to decode it server-side before storing it in the database. If you don’t decode TinyMCE output now, you’ll need to decode it before rendering anywhere.

public String SystemText
{
    get
    {
        return HttpUtility.HtmlDecode(bodyHtml.Value);
    }
    set
    {
        bodyHtml.Value = value;
    }
}

In codebehind (or wherever else you’re referring to your textarea in code), use HttpUtility to decode TinyMCE’s output when retrieving the value of the textarea for storage.

Handling TinyMCE re-encoding HTML on Postback

TinyMCE is set to encoding=xml, which encodes everything in the textarea on POST. That leads to a bunch of nasty &amp; &gt; etc. instead of real HTML when the page reloads after a Postback.

So, on Postback, we decode the textbox so TinyMCE is starting "clean". Here’s what sample codebehind could look like to do this:

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        if (bodyHtml != null && !string.IsNullOrWhiteSpace(bodyHtml.Value))
        {
            bodyHtml.Value = HttpUtility.HtmlDecode(bodyHtml.Value);
        }
    }
}

I’m very happy with this method; it works great using ASP.NET 4.0 and its more robust page validation model.

More importantly, I don’t have that nasty feeling I’m doing something terrible by setting ValidateRequest="false” in the page declaration!

Certificate signing isn’t a perfect answer for untrusted code, but it does give the user another indication that your Add-In will do what it says on the tin. More importantly, not signing your code when the installer framework expects a certificate isn’t a great way to make a first impression.

the-add-in-publisher-could-not-be-verified

Not cool.

Previously, we talked about automating builds of our Add-In’s installers and the parent *.wssx add-in package file, and my strategy for automatically building packages that support in-place upgrades.

Now we’re going to talk about signing our *.wssx package with a certificate, specifically a self-signed certificate for testing purposes.

Self-signed Certificates

Code signing certificates are usually more expensive than standard SSL certificates. While an SSL certificate authenticates a single web server (probably), a code signing certificate states that a specific piece of software was built by your company and hasn’t (probably) changed since it was built.

The difference in cost is that (theoretically) your company must be authenticated by the certificate issuer before they give you a certificate (by checking company registration records etc.).

Code signing certificates are valuable to malware authors – if they can get hold of a code signing certificate and private key for your company, they can write software that pretends it was written by you. Not great for your business' image if that happens (and it has, to some high-profile companies).

So, code signing certificates are more expensive than SSL certificates and should have their private keys protected against theft. What’s a self-signed certificate, then?

You can generate your own certificates and private keys using a variety of tools, and use them however you want. These are “self-signed” certificates, because they’re not signed by a trusted 3rd-party issuer (like VeriSign et al.).

Self-signed certificates are great for testing certificate signing processes, signing development code, and allowing automated builds that aren’t dependent on one person entering the secret private key for your expensive code signing certificate.

The only down side is that no one trusts your self-signed certificate, so you tend to generate the same sorts of errors as unsigned code because the issuer of the certificate (your development machine) isn’t trusted by anyone else.

That’s not a major issue for internal testing as you can make other computers trust your certificate (which we’ll talk about later). External testers can also trust your self-signed development certificate, or ignore the certificate error.

Creating a self-signed certificate

Visual Studio has all the tools you need to create and use a self-signed certificate.

I’m going to describe the command line method here, using Visual Studio tools. This method creates a self-signed Certificate Authority (CA) certificate that you can import into the certificate store on other computers so that they trust your self-signed certificate.

Using this method is a good idea if you need/want to create multiple code signing certificates; you won’t have to manually import each certificate because your target machines just need to trust your root CA certificate.

Credit goes to Roger Lipscombe on StackOverflow for these steps.

Start by opening Visual Studio Command Prompt (which opens in the right directory, and gives us the path variables that make things easier) or open Command Prompt and navigate to C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC (or wherever you’ve installed Visual Studio).

In the instructions below, substitute “Tentacle Software” for your own company or name.

Create your self-signed CA

Run the following command (it’s all one line, so watch out for line breaks) to create your CA certificate and private key file. Your self-signed code signing certificates will use this CA certificate as their root.

makecert -r -pe -n "CN=Tentacle Software CA" -ss CA -sr CurrentUser -a sha1 -sky signature -sv TentacleSoftwareCA.pvk TentacleSoftwareCA.cer

Note the *.pvk and *.cer file names; you probably want to give them a path (otherwise they’ll get created in the current working directory).

You’ll be prompted twice for a password for the private key. Use the same password for both prompts, and make sure it’s one you can remember.

image

image

Now we can import our CA certificate into our own certificate store so that we trust it.

certutil -user -addstore Root TentacleSoftwareCA.cer

Note the *.cer file name; make sure you’re using your own file name and not mine!

You’ll be prompted to accept the certificate, and you’ll receive a detailed warning about why accepting a CA that can’t be verified is a bad idea. They’re right, it is a bad idea! Unless you’ve created the CA yourself, of course.

Each time you create a code signing certificate, you’ll be using the CA *.cer and *.pvk files. So keep them safe.

Create your first self-signed code signing certificate

Using our new CA, we’ll create a code signing certificate we can actually use. We pass in the CA certificate and private key file as variables, and we output a *.cer and *.pvk for our code signing certificate.

A code signing certificate is referred to as a Software Publisher Certificate (SPC), which you’ll see in my example file names below.

makecert -pe -n "CN=Tentacle Software SPC" -a sha1 -sky signature -ic TentacleSoftwareCA.cer -iv TentacleSoftwareCA.pvk -sv TentacleSoftwareSPC.pvk TentacleSoftwareSPC.cer

Again, note the file names for our CA certificate and private key file. Make sure to use your own file names.

You’ll be prompted twice for the private key password for our new private key file, just as we were when we created the CA. If you’re feeling particularly security conscious, use a different password from the CA *.pvk.

You’ll also be prompted for the password to the CA *.pvk file, so our CA can officially sign our new certificate.

image

Now we want to convert our *.cer and *.pvk combo into a *.pfx file, which Visual Studio can use to sign our code.

pvk2pfx -pvk TentacleSoftwareSPC.pvk -spc TentacleSoftwareSPC.cer -pfx Key.pfx -po P@ssw0rd

We’ve got another password here, specified by the -po switch; you’ll enter this in Visual Studio when signing. Use something slightly more secure than I have here.

You’ll be prompted to enter the private key password of your SPC private key file, and Key.pfx is the final output file that we’ll add to our Visual Studio project.

Signing a *.wssx file

Our Windows Server Solutions Add-In Package Project Type (*.wssx) for Visual Studio 2010 supports post-build package signing, so we’ll make use of that functionality.

If you’re not using our *.wssx project type, you’ll need to play around with some post-build steps in MS Build, which I won’t cover here; we’re just running signtool with the appropriate switches.

Add Key.pfx to the package project

The first step is to add our final Key.pfx file to our project.

image

You can copy and paste Key.pfx from Windows Explorer into the project in Visual Studio, or right-click the package project and choose Add –> Existing Item.

Configuring signing in Debug builds

Our *.wssx project type supports different code signing properties per build configuration. This is great because it means you can use your self-signed certificate for Debug builds and your real SPC for Release builds.

To configure signing options, right-click the package project, choose Properties, and change to the Signing tab.

Make sure you’re in Debug configuration, set “Sign the package” to true and choose your certificate file from the drop-down list.

Because we set a password on our *.pfx earlier, we need to enter an additional signing option (“/p P@ssw0rd”) to tell signtool to use our password.

image

Post-build signing

Now whenever we build our package in Debug mode, it will be automatically signed with our self-signed *.pfx Software Publisher Certificate.

Our *wssx project type also verifies the signature after signing, so that you can be sure the certificate signing process completed successfully.

Trusting a self-signed certificate

So, what does our self-signed package look like now when we install it?

the-add-in-publisher-could-not-be-verified

Pretty much the same.

In order for the Windows Server Solutions package framework to trust our self-signed certificate, it needs to trust our imaginary Certificate Authority.

Installing the CA certificate

Copy your CA certificate from your development machine to the server you’re deploying your Add-In packages to (using our example file names, that’s TentacleSoftwareCA.cer).

Double-click the certificate and you’ll be presented with the certificate’s details.

image

Click “Install Certificate” and step through the import wizard. You want to place the certificate into the Trusted Root Certification Authorities store.

image

You’ll be prompted about how much of a bad idea it is to trust random root CA certificates. We know where this one came from, so click “Yes” to install it. You’ll receive a success confirmation dialog at the end.

This server now trusts all certificates issued by our fake CA, including our new code signing certificate.

If you Add-In package deploys client binaries, those client machines will need to trust our CA too. You’ll need to repeat the above process on each client machine.

Installing a trusted *.wssx package

What happens when we install a *.wssx package that’s been signed with a certificate issued by a CA we trust?

image

Not much! The nasty untrusted code error isn’t shown, and we go directly to the EULA screen.

This is a much better experience for your customers; remember that your installer is the first impression you get to make regarding the quality of your software, and big red error messages about untrusted code tend to make users slightly uncomfortable.

Release mode signing

Once you’ve built your Add-In, tested it, and you’re ready for release, you’ll need to purchase a production code signing certificate from a Certificate Authority that Windows trusts by default. Costs vary wildly here, so do some research.

When you have your *.pfx file ready, you can edit the Release mode configuration for your *.wssx package project and enter the relevant details.

Depending on your company’s certificate policies, this may mean delay signing or not signing automatically at all – final package signing can be performed manually using signtool by the person who has access to the private key of your production certificate.

Now, go forth and certify!

Search

Site Sections

Recent Posts

Archives

Post Categories

WHS Add-In Tutorial

WHS Blogs

WHS Development