Welcome to MSDN Blogs Sign in | Join | Help

ClickOnce and Security

ClickOnce deployment is another area where Code Access Security needs to be kept in mind. ClickOnce deployments will often be used to deploy Visual Basic .NET (or hybrid Interop Toolkit) applications from a website or network file share. In these cases, the applications don't get the standard Full Trust permissions in CAS. Instead they get the more limited Internet Zone permissions. As a developer, you will need to ensure that your application can run successfully with this permission set. Visual Studio can help out here, so rather than having to mess around with your security policy while you're debugging, Visual Studio can set up a debugging session with the required permissions (look on the Security page of your project properties to see how to configure this behaviour).

If the set of permissions granted to the Internet Zone aren't sufficient then you have two options:

  1. Ask for the additional permissions in the ClickOnce deployment manifest, and rely on the user accepting the elevated permission request during the install.
  2. Ask your administrator to configure the standard CAS policy on end user machines to permit elevated permission requests from specific publishers. You then use Authenticode to sign the deployment manifest, using the permitted publisher details.

Option 2 is obviously to be preferred, but needs a bit more work to get set up.

Introducing code obfuscation

If you recall from an earlier post, I said that the main reason for signing an assembly and giving it a strong name was to prevent it being tampered with. For example, many of the assemblies that make up the .NET framework itself are strong-named assemblies that sit in the GAC. If I disassembled one of these, messed around with the IL code, and then reassembled it, I'd have to sign it with my signature. Running any existing applications that used the assembly I'd changed would now fail, because the signature had changed. That's all great in that it stops anyone tampering with existing, deployed assemblies.

What may still be a concern is that the IL code is still legible, so that anyone can see how your code works and what it does (provided they spend a bit of time getting familiar with IL code). This raises the issues of intellectual copyright and opens the potential for security breaches as unscrupulous developers can easily look for weaknesses in your application.

Enter code obfuscation (Dotfuscator on Visual Studio's Tools menu). This utility renders the contents of your assemblies (the IL code), incomprehensible to human readers, but leaving it so that it can still be run by the CLR. This is done by renaming everything in sight, variables, classes, methods etc with meaningless or duplicate names. Obfuscation is an excellent demonstration of how useful good names are to understanding code!

Code Access Security in action – calling Unmanaged Code

The following is an example of how code access security might affect your code when calling unmanaged code. Unmanaged code is a posh way of saying “It isn’t .NET code, it is the stuff you used to write before .NET” :-)

In VB6 making a call to a Windows API function wasn't affected by any security settings. Potentially in .NET, an administrator might configure a machine's code access security policy to disallow calls to unmanaged code (such as the Windows API), because this is seen as a security risk. That means that code like this, could fail with a SecurityException, when the API function is invoked:

   1:  Module Module1
   2:      Sub Main()
   3:          Win32.MessageBox(0, "Here's a MessageBox", "Platform Invoke Sample", 0)
   4:      End Sub
   5:  End Module
   6:   
   7:  Public Class Win32
   8:      Declare Auto Function MessageBox Lib "user32.dll" ( _
   9:          ByVal hWnd As Integer, ByVal txt As String, _
  10:          ByVal caption As String, ByVal Type As Integer) _
  11:          As Integer
  12:  End Class

There's nothing you can do to stop the code failing (other than having a word with the administrator), but you can handle things a bit more gracefully. You can check when your app starts up whether you've got all the permissions you want, and then handle the situation before you hit the problem. This can be done with an attribute (declaratively), so the permissions are checked when an assembly is loaded:

<Assembly:SecurityPermissionAttribute(SecurityAction.Demand, Flags := SecurityPermissionFlag.UnmanagedCode)>

You could also perform the check programmatically:

   1:  Try
   2:          Dim sp As New SecurityPermission(SecurityPermissionFlag.UnmanagedCode)
   3:          Console.WriteLine("Demanding SecurityPermissionFlag.UnmanagedCode")
   4:          sp.Demand()
   5:          Console.WriteLine("Demand for SecurityPermissionFlag.UnmanagedCode succeeded.")
   6:          Catch e As Exception
   7:              Console.WriteLine(("Demand for SecurityPermissionFlag.UnmanagedCode failed: " & e.Message))
   8:  End Try

Either way you can test for the permission before you need to use it.

The above checks whether you had the necessary permissions to perform an operation (in this case calling unmanaged code) by using Demand. You can also Assert or Deny a permission.

  • SecurityAction.Demand
    What in fact you're doing here is checking that your assembly has the requested permission, and that any assemblies above you in the call-stack also have that permission.
  • SecurityAction.Assert
    This is a little bit different. You're still checking that your assembly has the requested permission, but you're also saying to the CLR - "Don't bother about checking further up the call stack". In effect, you are taking full responsibility for security. This is usually seen as dangerous behaviour, but there are some circumstances where it's useful.
  • SecurityAction.Deny
    Here you're saying you don't want a permission. Not at first sight much use, because if you don't want to be able to do something, then you won't write any code to try and do it! However, this also switches off the permission for any assemblies that you call (that might have been written by someone else), unless of course they go ahead and do an Assert!

Authenticode and ActiveX controls

For VB6 developers, one area where asymmetric keys and digital signatures cropped up was the requirement to sign downloadable ActiveX controls using Authenticode. The idea was to sign the controls using a digital signature so that the origin of the control could always be established.

There are a couple of related concepts in .NET that you'll almost certainly come across sooner or later.

Code Access Security

With ActiveX controls, the default behaviour of Internet Explorer was to prevent their download unless they had a valid signature. In .NET the CLR applies a security policy to all loaded code. The CLR evaluates the code and then decides what that code should and should not be able do. So the CLR will look at a particular assembly, see if it has been signed or where it was loaded from etc., and then decide whether that code is allowed to write to the hard disk or open a network connection and so on. All of these policy rules are stored in configuration files, which in previous versions of the framework you could see and edit using a control panel applet. In .NET 3.5 you're expected to edit this configuration using the command line caspol.exe tool (unless you install the .NET 2.0 SDK).

Strong Names

.NET also uses the concept of strong named assemblies. At first sight this looks similar to signing a component using Authenticode, in that strong named assemblies are digitally signed. However the digital signature is used for very different reasons. First of all, if you want to place an assembly in the Global Assembly Cache (GAC) , it must have a strong name. The digital signature makes your assembly unique, even if someone else has installed an assembly with the same name into the GAC. Secondly, a strong name prevents unauthorised tampering with an assembly. So, although someone can disassemble a strong named assembly using Ildasm, they can't put it back together again with the same signature (unless you've given them your private key!). Any change in the signature is automatically detected by users of the assembly, and the tampering spotted. Strong naming is done with the Sn tool.

Cryptography

The second big security area in the .NET framework after Authentication and Authorisation is cryptography. Again, the framework contains a lot of powerful functionality, and again there is an application block that makes it all a bit easier to use.

The classes and namespaces that deal with cryptography cover three key areas:

  • Symmetric Key Encryption/Decryption
  • Asymmetric Key Encryption/Decryption (Public Key Cryptography)
  • Hashing

I don't want to get bogged down in the detail of these three topics (there's plenty of resources elsewhere on the web for that), but just highlight where, in a VB application, these technologies may be useful.

Symmetric Key Cryptography

This kind of encryption algorithm uses a single shared key that can be used to both encrypt and decrypt data. These algorithms are also relatively fast. The fundamental weakness of this approach is that both the encrypting and decrypting parties need to know the same key, and to make sure that no one else has access to the key. The framework includes implementations of a number of well known algorithms of this type such as DES, TripleDES and AES.

Where this is useful in a VB application is where the application wants to store it's own data securely - perhaps as a file, or a section of a configuration file, or a registry key. A couple of useful classes are ProtectedMemory and ProtectedData which look after all the key management issues for you.

Asymmetric Key Cryptography

While these algorithms are slower than the symmetric ones, they don't rely on a single shared key. Instead, they use a pair of keys, on public and one private, where data encrypted with one key can only be decrypted using the other. These algorithms, as well as providing encryption, also form the basis of digital signatures.

This approach is appropriate when exchanging data securely between users or systems. The HTTPS protocol is an example of the use of this approach.

Hashing

You can think of hashing as a one way system, you can encrypt (hash) a piece of data to generate a unique hash code, but you can't work out from a hash code what the original piece of data was. What's the use of this then? An authentication system that verifies passwords is a good example:

You need to check that a user password is correct when they log on - so you need to keep a record of passwords somewhere and the password needs to be transmitted over the network from the client application for checking. This gives you two security loopholes - passwords stored in a database and passwords flying around on the network. If you store a hash of the password in the database, and the client application sends a hashed version of the password for checking we've avoided both problems! We just need to compare hash values to check if the password is correct.

The framework includes implementations of a number of hashing algorithms including SHA and MD5.

Authentication and Authorisation

As promised, the first in a series of posts about security relevant to a developer new to .NET (such as a VB6 developer).

These are what most people will immediately think of when security is discussed.

  • Authentication
    This is proving your identity by some means, whether it's knowing your password, having the right swipe card or having your fingerprint checked.
  • Authorisation
    Once a system knows who you are it can apply some rules to decide what you can see or do.

ASP.NET has a huge amount of built-in support for performing authentication and authorisation (a far cry from the situation with ASP) including a full-blown membership system that simplifies creating a web site that requires registration before you can access certain areas of the site.

Authentication and authorisation have tended to be less significant when developing desktop based systems because a) it is a more "controlled" environment and b) the desktop OS can be left to handle these issues for you.

A common scenario where you do need to customise things is where a desktop application needs its own authorisation rules (we can still rely on the OS performing the authentication for us, typically against Active Directory). What we want to do in our application is authorise users using Active Directory (or ADAM) - to minimise the development effort here you should look at the Security Application Block.

What (or who) is ADAM, some of you are asking? Simply put  Active Directory Application Mode is a standalone version of Active Directory that you can distribute with your application. Therefore you could have you own authentication database which could also be customised without impacting Active Directory itself.

While I'm on the subject of application blocks, there are a couple of others that relate to security. There's a Cryptography Application Block which I'll talk about in a later post, but for now I wanted to point out the Logging Application Block. This is great if you need to record what's going on in your application for troubleshooting, error reporting, or from the security standpoint, auditing.

Creating log entries from your code is straightforward:

   1:  Dim logEntry As LogEntry = New LogEntry()
   2:  logEntry.EventId = 100
   3:  logEntry.Priority = 2
   4:  logEntry.Message = "User Logon: " + userName
   5:  logEntry.Categories.Add("Audit")
   6:  logEntry.Categories.Add("UI Events")
   7:  Logger.Write(logEntry)

The configuration options of the application block then enable you to control things like where the log messages get written to, and to define filters based on LogEntry fields.

Possible destinations for log messages include: a database, the Windows Event Log, a rolling flat file or an email.

Visual Basic .NET and Security – a few posts are required

One of the reasons for moving to VB.NET from VB6 may be the more advanced security models available in the .NET Framework - this is particularly relevant in the ASP.NET world where many .NET applications will need a security system. In the desktop arena, there may also be requirements for security features over and above those provided by the OS, which would be difficult to implement with VB6.

Even if you don't need any new security features, you can't avoid security in .NET, as it is "built-in".

The three main areas of security in the Framework are:

  • Authentication and Authorisation
  • Cryptography
  • Code Access Security (CAS)

It's the last one, CAS, which probably needs most explanation for newcomers to .NET.

I will take a look at security over the next week or two on this blog… which should be useful recap for me as well :-)

Virtualization and Visual Basic 6.0 applications

There may be some circumstances where upgrading a VB6 application is not feasible, for example it may rely on a control that simply does not work in the target operating system. I came across a couple of articles on MSDN that discussed the ways that virtualisation technologies can be applied to this problem. There are three basic approaches:

  1. Run all, or in a virtual machine. Virtual PC, Virtual Server or Hyper-V in Windows Server 2008 are all possibilities.
  2. Use Terminal Services to give end users access to the application.
  3. Use Microsoft Application Virtualization (formally Softgrid) to virtualize a part of the application.

Check out these links:

Posted by Eric Nelson | 1 Comments

In VB6 we had the API Viewer, In VB .NET you get the P/Invoke Interop Assistant

VB6 programmers will remember a useful little utility called the API Viewer, the helped out when you needed to make a Windows API call.

clip_image002

There is now an equivalent tool for .NET, the P/Invoke Interop Assistant (http://www.codeplex.com/clrinterop ). Not surprisingly it does a little bit more, so as well as enabling you to look up the signature for a particular call, it will also translate snippets of C code.

clip_image004

Notice that it generates required structure definitions to go with your function call!

I also noticed that the P/Invoke Interop Assistant generated code that used the DllImport approach to setting up the API call. I expect this question has been answered loads of times before, but what are the advantages of using DllImport rather than Declare in your VB code? The obvious answer is that DllImport is a .NET way of doing things, but for VB6 programmers of the Declare statement looks much more natural. DllImport does offer much finer control over the way the call is made, but unless you need this fine control you can stick with Declare.

Enhancing your VB6 Application with Interop

I’ve been having a look at some of the samples on the Visual Basic Resource Center to see what’s possible when we start using interop between VB6 and .NET. Here are some of my favourites.

This article, “Sharing ADO Recordsets Between Visual Basic 6 and Visual Basic 2005”, looks at approaches to sharing data between VB6 and .NET using the Interop Forms Toolkit. It also serves as a great reminder of the fact that Recordsets can operate in a disconnected mode just like a more modern Dataset. This disconnected mode is the mechanism used to shift the Recordsets from VB6 to .NET and back again.

In the past, creating a multithreaded application in VB6 has been a bit of a challenge. Using Interop it’s now much easier to add this kind of functionality to a VB6 application. The trick here is to make use of the BackgroundWorker component (you could easily apply the same approach using any .NET component from VB6). See “Using Background Threads with Visual Basic 6”.

ClickOnce deployment offers a very clean and simple model for delivering applications to the user’s desktop. At first sight it doesn’t look as if it would be possible to use ClickOnce to deploy a VB6 application because of all registration issues, but this blog post here by Beth shows you how you can make it work.

Adding to the My namespace in VB .NET

Just as an aside - after experimenting with the Interop Forms Toolkit earlier this year I wondered how InteropToolbox ended up in the My namespace – it seems like a useful thing to be able to do. I didn’t have to look far, the answer was in the ActiveXControlHelpers.vb file in my Usercontrol project:

   1:  'Adds the InteropToolbox to the My namespace
   2:  Namespace My
   3:      'The HideModuleNameAttribute hides the module name MyInteropToolbox so the syntax becomes My.InteropToolbox.   
   4:      <Global.Microsoft.VisualBasic.HideModuleName()> _
   5:      Module MyInteropToolbox
   6:   
   7:          Private _toolbox As New InteropToolbox
   8:   
   9:          Public ReadOnly Property InteropToolbox() As InteropToolbox
  10:              Get
  11:                  Return _toolbox
  12:              End Get
  13:          End Property
  14:      End Module
  15:  End Namespace

You might want to have a look at this as well.

Posted by Eric Nelson | 1 Comments

That old friend Binary Compatibility – and a FREE eBook on COM Interop

A favourite topic for VB6 programmers! Adding a reference to a COM component in Visual Studio adds a reference to a specific version of the VB6 component, so rebuilding the VB6 component without binary compatibility will break the .NET project (you’ll have to re-add the reference to fix it). Switching on binary compatibility in the VB6 project will bring its own set of problems, so a better solution for an automated build would be to run TlbImp on your VB6 dll in your .NET project’s Pre-build event.

I just discovered that TheServerSide.NET has a free book available covering all of the intricacies of .NET to COM interop , so if you want to delve any further take a look here: COM and .NET Interoperability.

VB6 Migration tools are not as expensive as you might think

How long would it take you to manually convert 50,000 line of Visual Basic 6.0 code to Visual Basic .NET. My guess is… quite a long time :-)
However two of the key partners in this space have special versions of their enterprise class tools targeting 50,000 and below for a great price.

Interestingly Artinsoft now have a sliding scale of prices public on their website. Well done guys.

  • 25K Lines $249.00
  • 50K Lines $499.00
  • 75K Lines $749.00
  • 100K Lines $999.00
  • 150K Lines $1,499.00

Aberdeen Group report on Migrating from VB6 to .NET

Aberdeen Group have created a new report “Migrating from VB6 to .NET: The challenge of software agility in a volatile economy

Some bits that stood out for me:

  • 50% will migrate all the applications, 36% will migrate some (86% in total will migrate)
  • “Best in class” understand the importance of external migration services and tools - 30%+ in each category
  • 14% of organisations said their entire environment is VB6 based.
  • For those who will NOT migrate to VB.NET:
    • 62% will migrate to C#
    • 10% Other .NET languages
    • 16% Java (tut tut)
    • 12% Other none .NET

Visual Basic 6.0 Migration – due diligence is a good thing

Choice in general is a good thing. When faced with moving a Visual Basic 6.0 application to .NET there is plenty of choices to be made. One of those choices is “Which tool should I go with to migrate the code?”.

My advice in general is “Try as many as you can on a representative chunk of your application”.

I spotted over on the VB Migration Partner website a case study which contained an example of just that:

“During the software evaluation phase SIS run a 25K prototype through all the conversion programs. It took 2.5 hours to get a compilable and runnable VB.NET project with VB Migration Partner, and 13 hours with its closest competitor. The reduced effort, the ability to use pragmas and support for the convert-test-fix were the main reasons for choosing Code Architects’ software.”

This was a 650K Lines of Code conversion in just 6 months with a total effort of 18 man-months. Pretty impressive.

P.S. 13/2.5 = 5 times faster, in case you were wondering :-)

More Posts Next page »
 
Page view tracker