Click here to Skip to main content
Click here to Skip to main content

Using MSI or a Strong name to store .NET apps on a network server (Part 2)

By , 7 Jun 2005
 

Sample Image - Using_MSI_or_a_strong_na2.jpg

Introduction

Here is part 2 of the series on putting .NET applications on the network and getting around the security issues. This time I will be describing how to use a strong name key pair to mark an assembly as a strong named assembly, then we will do something similar to the last article in marking that strong name key as fully trusted. If you did not get a chance to read part one, you might want to take a few minutes to read it.

Background

So there are options in .NET for distributing applications. If you have a local intranet you can host an ASP.NET application. This can be somewhat limiting for extremely complex applications that are better suited for a Windows style application. It is not always easy to release something new on the web either, even if it is your local intranet. You can use a web server to help distribute the application. Something like: it checks to see what version you have locally and if there is a newer version it is installed locally and then launched. You can use a terminal server. The application only exists on the terminal server and your users have to log into the terminal server to access the app. We have tried all these approaches and personally I don't care much for them. So on to the next two. First, the one I like best, create a machine level runtime security policy. Then put it into a MSI script and have your users run the MSI script (they only have to once), or have Active Directory distribute the MSI script at login. This policy marks a network server and folder on that server as fully trusted. The other option is to use the SN.exe tool to create a strong name key and mark all of your applications with the strong name key and then create a runtime security policy allowing anything with that strong name key to be fully trusted. In part 2 of this article, I will be reviewing how to do the machine level runtime security policy that marks a strong name key as fully trusted.

One more thing to know here on strong name keys. When I first started working with them, I assumed that you have to create a new strong name key pair for each application. Well, of course, that is silly. You should in fact only have one strong name key pair and reuse it for any assemblies you want to mark as strong name assemblies. Of course there are good reasons to use different strong name keys, but that is a subject for a different discussion.

How do you do it...

Let's start off again with what you get when a .NET app is not fully trusted.

Sample screenshot

Next we need to create the strong name key pair. You use the SN.exe tool for this. If you have Visual Studio installed then you can open a Visual Studio .NET command prompt. This allows the command prompt to know what the SN.exe is, otherwise you will need to navigate to where the sn.exe program resides which is in the .NET framework folder. Navigate to the folder you want the strong name key to be created in. The command is sn -k filename.snk:

Sample screenshot

Next you need to consume the strong name key pair in your .NET app. Open your AssemblyInfo.vb or AssemblyInfo.cs file and add this code:

'vb.net

<ASSEMBLY: AssemblyKeyFile("c:\keys\Liberty.snk")>
//or C#

[assembly: AssemblyKeyFile("c:\keys\Liberty.snk")]

Note you will need to point to your file path and key file name. You can also use the AssemblyKeyName attribute. Now you will need to compile your .NET app. This is important since the easiest way to get the strong name public key is to import an assembly that already has it compiled in.

Creating the code group

Now we will follow the familiar process from part 1 of creating a new code group. On to creating the run time security policy that marks a strong name key pair as fully trusted. You set up a machine level runtime security policy in the .NET framework configuration tool, which can be found in Control Panel->Administration tools. Note that if you are not an Administrator on your PC, you will not be able to set a runtime security policy. Under Runtime Security Policy\Machine\Code groups\All code\localIntranet_zone\, you want to add a child code group.

Sample screenshot

Put in a name and comment for the new code group:

Sample screenshot

Now you will need to select a strong name from the drop down. Then click the Import button and select the .NET app you just compiled with the strong name key. This will bring in the strong name public key into the code group dialog.

Sample screenshot

Next you need to select what security you want this folder to have. Full trust is what I usually pick, but there are several options. Then click Next and finally click Finish. At this point you would be able to launch a .NET Windows app from the server\folder you just set up in a code group and you would not get a security violation.

Creating the MSI script

On to creating the MSI script for this code group. Click on the runtime security policy. You should see an option for creating a deployment package. Click that option.

Sample screenshot

Next you should select the machine on the radio group and put in a local path and name for the MSI script.

Sample screenshot

Click Next and click Finish.

Conclusion

Now you have an MSI script that people can run, they only have to do it once, and they will be able to launch a Windows .NET app from a network server and they will not get a security violation. Note, when the MSI script is run, it will replace any current runtime security policies on the machine level. You can distribute the MSI script over Active Directory, but I will not include that in this article. I am planning on writing a third article on this subject. Since the main down side to distributing .NET apps on a network server is that, when you need to release a new version, if someone is in the app you can not copy over the new version, I have written an app that allows you to see all the files on a network server and who has those files open. That way you would know who to notify, that is who to ask to get out of the app so you can release it. (I do realize that if you have admin rights to the network server you have access to this information already, but for those of us who are not admins on the network server...).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

kubben
Web Developer
United States United States
Member
I started my programmer career over 16 years ago doing COBOL and SAS on a MVS mainframe. It didn't take long for me to move into windows programming. I started my windows programming in Delphi (Pascal) with a Microsoft SQL server back end. I started working with vb.net when the beta 2 came out in 2001. After spending most of my programming life as a windows programmer I started to check out asp.net in 2004. I achieved my MCSD.net in April 2005. I have done a lot of MS SQL database stuff. I have a lot of experience with Window Service and Web services as well. I spent three years as a consultant programing in C#. I really enjoyed it and found the switch between vb.net and C# to be mostly syntax. In my current position I am programming in both vb.net and C#. Lately I have been using VS2012 and writing a Windows 8 app. You can search for the app it is called ConvertIT.
 
On a personal note I am a born again Christian, if anyone has any questions about what it means to have a right relationship with God or if you have questions about who Jesus Christ is, send me an e-mail. ben.kubicek[at]netzero[dot]com You need to replace the [at] with @ and [dot] with . for the email to work. My relationship with God gives purpose and meaning to my life.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionDo I still have to run MSI script on each client for strong names?membermccalla10 Dec '07 - 3:58 
Hi,
 
I thinking of using the strong name solution to the security problem my app is having because it is being deployed in a shared network server.
 
I create the strong name, added to my assembly file, and now plan on creating code group on the network server.
 
2 questions:
 
Do I need to reboot network server after I make code group change?
 
Do I still need to create a MSI script to be run on each client server?
 

 
Thanks in advance,
 
mccalla
GeneralRe: Do I still have to run MSI script on each client for strong names?memberkubben12 Jan '08 - 1:44 
Sorry I am just responding now. I did not get the notification when you posted your question.
I would guess you have already figured out the answers to you questions.
 
You asked:
Do I need to reboot network server after I make code group change?
No, there is no need to reboot the network server after the code group change.
 
Do I still need to create a MSI script to be run on each client server?
Yes, each client needs to trust the strong name so it will have the proper trust level when it accesses something on the network share.
 
Ben
QuestionProblem not solved.memberChellathurai7 Nov '06 - 19:21 
We have a web application,from there we want to invoke an exe.So it results in the same security error.Even though we had done this the security problem occurs.Any Solutions???
 
C.Babu
AnswerRe: Problem not solved.memberkubben8 Nov '06 - 2:34 
Most of the time, if you still get the security error it is one of two things.
First, you didn't create the msi script correctly.
Second, you don't have admin rights on the PC that you ran the MSI script on.
 
My guess is that you don't have admin rights on the PC you ran the MSI script on. You don't get any indication that the MSI script didn't work. It just runs, but when you are not the admin it can't do anything since you don't have rights.
 
I hope that helps.
 
Thanks,
Ben
GeneralAdministrator vs Non Administratormembermightymuke17 Sep '06 - 15:12 
Hi there,
 
I've followed the process as you've described, created the code group, then created the MSI, and ran the MSI on a machine with administrator rights, and the could see the entry in the security.config file, and the application on the network share ran perfectly.
 
Then I ran the MSI on a machine without administrator rights. I received no errors when the installation ran. The applicatition on the share still failed with a security error, and when I checked the security.config file on this machine, there was no entry for the new code group to be found.
 
Should I expect this to work?
GeneralRe: Administrator vs Non Administratormemberkubben17 Sep '06 - 17:00 
Hello,
 
When you run the MSI script on the PC you must run it as an admin. Otherwise the script really doesn't do anything. There are some active directory ways of pushing out msi scripts to all PC's. A Network admin would probably have a better idea how to do that. Hope that helps.
 
Ben
GeneralGreat Article Benmembermpemberton30 Aug '06 - 4:51 
Thanks for putting this together Ben. Definitely helps. Figured I'd add an extra piece to the puzzle for anyone interested.
 
This piece of code (which I cannot claim for myself) allows you to programmatically add your new codegroup to the machine policy settings. If you host your app on a server, throw this into a simple app and run it on each workstation using your method of choice.
 
            ' Produce the public key by secutil -c -s <dll or exe entered here>
            Dim publicKey As Byte() = {0, 36, 0, 0, 4, 128, 0, 0, 148, ..., 41, 17, 223, 92, 180, 207, 31, 78, 6, 193}
 
            ' Machine Policy Level
            Dim machinePolicyLevel As PolicyLevel = Nothing
            Dim ph As System.Collections.IEnumerator = SecurityManager.PolicyHierarchy()
 
            'Determine Policy Level
            While ph.MoveNext()
                Dim pl As PolicyLevel = CType(ph.Current, PolicyLevel)
                If pl.Label = "Machine" Then
                    machinePolicyLevel = pl
                    Exit While
                End If
            End While
 
            'Just in case???  Should never happen
            If machinePolicyLevel Is Nothing Then
                Return
            End If
 
            'Check if Group already exists
            Dim codeGroup As CodeGroup
            Dim machineCodeGroupRoot As CodeGroup
            For Each codeGroup In machinePolicyLevel.RootCodeGroup.Children
                If codeGroup.Name = "My Group" Then
                    MsgBox("Permissions Exists")
                    Return
                End If
            Next codeGroup
 
            ' Set the new codegroup to have FullTrust permissions
            Dim permSet1 = New NamedPermissionSet("FullTrust")
            Dim key As New StrongNamePublicKeyBlob(publicKey)
            Dim membership1 = New StrongNameMembershipCondition(key, Nothing, Nothing)
 
            ' Build the CodeGroup
            Dim policy1 As New PolicyStatement(permSet1)
            Dim codeGroup1 = New UnionCodeGroup(membership1, policy1)
            codeGroup1.Description = "This is a description."
            codeGroup1.Name = "My Group"
 
            machinePolicyLevel.RootCodeGroup.AddChild(codeGroup1)
 
            SecurityManager.SavePolicy()
 
Enjoy! And I too am a born again Christian who has accepted Christ as my Savior and He is the ONLY way to Heaven. Thanks for being bold Ben!

GeneralRe: Great Article Benmemberkubben30 Aug '06 - 4:59 
Thanks for posting this code. I am sure there is an assumption that the user running this code is an Admin on the box. It is nice to know another way of doing things.
 
In Christ,
Ben
GeneralRe: Great Article Benmembermpemberton30 Aug '06 - 5:08 
Yes, you are correct. An admin will need to run this. Thanks for clarifying that. We're a pretty large installation and we'll probably push this out via SMS or however the windows admins will want to do it. Smile | :)
GeneralSigning Assembly in VS 2005memberIraGladnick5 May '06 - 6:50 
Great article!Cool | :cool:
 
For people using VS 2005, there is actually now an easier way to sign an Assembly.
 
Just open the property window for the project, and click on the the Signing tab. Then select "Sign the assembly", and choose the key file from the dropdown list.
 
There is are also options for specifying a password for the key file and for delayed signing on this tab.
 
Just thought I would mention this..
 


GeneralRe: Signing Assembly in VS 2005membermpemberton30 Aug '06 - 5:18 
I'm glad you mentioned this. Thought I'd add my 2 cents regarding what I found. It appears that there is a number of differences with the security between 2003 and 2005. Using a couple highly simplistic apps, the one's created with 2003 would not run at all (without adding security), but the 2005 apps would. For example, I had an app that I created in VB.NET 2003 which had two forms containing some buttons and text boxes and that was it. I compiled it and attempted to run it from a shared network drive. It failed to run (debug stated it was failing at the end of sub new(). Interesting. Then I converted it to 2005 and attempted to run it from the same network drive. It actually ran. Very interesting. (I hope I explained that ok).
 
So what does this mean? Probably not much, but thought I'd share it with you. M$ definitely has revamped a lot of the security settings in 2005/2.0. I'm still going to have to stick with 2003 since we don't have framework 2.0 on all clients. However, I'm having to write to a temp file on the client, so I'm going to have to have a codegroup anyway.
 
Blessings,
Mark
GeneralLogging access to shared filessussevilnoodle south africa18 Oct '05 - 4:11 
Hi everyone
 
I'm totally new to .Net and the company I work for are now making the move from vb6 to vb.Net. The code using the OpenFiles.exe sound more or less like what we need but it's a little over the top for me at this moment.
Basically I want to create a textfile log of all shared files accessed (over the network), when, for how long and by whom. So far your code is the closest I got to a solution.
 
Any suggestions or useful links I can follow?
 
Thanks!
woNTioD - 3vlndl3

GeneralRe: Logging access to shared filesmemberkubben18 Oct '05 - 8:06 
Well, unfortunatly the openfiles.exe will only tell you that someone is in the files. You would probably need to write something that kept track of when the user first accessed the file and when they got out.
 
If you install the openfiles service on the network file share it will start to produce an XML file (which is a .net dataset) every minute that contains who is in what file. They overwrite after 60 minutes. The client app I wrote to go with it reads in the xml file and displays it.
 
So if you want to know when someone started looking at a file and how long they had it open, you would have to write some code that would process the xml file outputs and write out the correct txt files you need.
 
Sorry if this wasn't very helpful, I suppose sooner or later you will have to dig in and learn .net.
 
Ben
Generalreligion and technologysussAnonymous14 Oct '05 - 9:40 
Why would you mix religion with technology in your article.
 
How lame would it sound if i put the following at the end of every one of my emails.
 

On a personal note I am a born again Muslim, if anyone has any questions about what it means to have a right relationship with Allah or if you have questions about who Mohammed is, send me an e-mail. spiritual_solicitor@inyourface.com My relationship with Allah gives purpose and meaning to my life, because of course, my relationship with my wife, kids, family, friends, and peers isn't enough.
GeneralRe: religion and technologymemberkubben16 Oct '05 - 15:31 
Dear Anonymous,
 
Thanks for your note. I am sorry if my personal bio offends you. Still I make no excuses for it. The whole point of having a personal bio is so that you get to know someone a bit better. I can honestly say that as much as I enjoy programming, my relationship with God is so much more important. Yes even more then my wife, kids, friends. And you are correct that I believe that as much as I love and care for (wife, kids, friends) they can never satisfy me the way my relationship with God does.
 
Let me ask you this. If you found the Truth and it changed your life, wouldn't you want to share it with others? How could you keep your self from sharing what has happened in your life. I have always from an early age needed to know what is life all about? What is my purpose? I can tell you that only by a right relationship with God have I come to know True Peace and fulfillment. I can't help but say something so that others may know this same joy.
 
I wish you a blessed Ramadan and pray that as you seek God, He will reveal to you who Isa truly is, Son of God and Savior.
 
Ben
GeneralProblem with ImportingmemberMerlinblack12 Jul '05 - 17:21 
I've tried this with a small Managed C++ console app. I could never get the importing of the strong name to work. I allways get a error complaining about an invalid assembly. However running:
sn -v myprog.exe
 
Says the assembly is valid!
 
Has anyone else run into this?
 
Thanks.
 
Nigel Atkinson
 
"Land a'hoy!" * CRASH * "I should av said that sooner eh?" - Eckles, The Goon Show
GeneralRe: Problem with Importingmemberkubben13 Jul '05 - 2:46 
First I should tell you up front that my C++ skills leave something to be desired. So take my advise for what it is worth, which is pretty much just guessing. Anyway, I was guess that the part of the C++ code where you attach the strong name key to the C++ assembly isn't quite working. There you have it my best guess.
 
Ben
GeneralRe: Problem with ImportingmemberMerlinblack17 Jul '05 - 17:10 
Thanks for your reply. I havn't got to the bottom of the problem yet, however I have got the strong name working. As far as I can tell, the key pair I generated is being compiled into the C++ program correctly,D'Oh! | :doh: as the process is almost identicle as VB and C#.
 
What I did was make a very simple VB console program that does nothing except output some text and add the same key pair I was using for the C++ program. Then I used this exe to import the key pair into mscorcfg.
 
This worked, and now both the VB and C++ app work as expected. I think (not totally sure) all mananged C++ programs have an unmanaged stub, which might prevent importing the strong name key pair?WTF | :WTF:
 
Anyhow I hope this helps others.Big Grin | :-D
 
Thanks
 
Nigel Atkinson
 
"Land a'hoy!" * CRASH * "I should av said that sooner eh?" - Eckles, The Goon Show
GeneralRe: Problem with Importingmemberkubben18 Jul '05 - 2:36 
I am glad you figured the strong named key thing out. I am sure your hard work will benefit others. Thanks for letting us know what happened.
 
Ben
GeneralStrong name vs URLmembergterziev1 Jul '05 - 1:42 
I have developed a Windows.Forms.UserControl, which is embeded in a Web page in Internet Explore. To work this control properly I have to create a group in Runtime Security Policy and give this group a permission set with granted 'Allow calls to Unmanaged Code' and 'Assert any permission that has been granted' permissions. When the Membership Condition is set with URL condition type, my control works as expected. But the case isn't the same when I have used the Strong Name condition type. IE just not activate the control, without any error messages or exceptions. In order to sign my assembly with strong name, I have created key pair with 'sn -k keypair.snk' command line, and added '[assembly: AssemblyKeyFile(@"..\..\keypair.snk")] line to my source code. After that I have verified the signature with 'sn -f ' comman line and it has told me that my assembli is valid. Can anybody explain me what is wrong?
GeneralRe: Strong name vs URLmemberkubben1 Jul '05 - 3:26 
First I will tell you straight up that I don't know the answer. Still I have some thoughts. Even though the assembly has a strong name you still need to create a code group where the strong name key is marked as trusted. Next it seems that every user that might access the page that uses that control may need to have that code group installed. If it is not running there then the web server itself would probably need the code group for the assembly to be marked at trusted.
 
Anyway, those are my thoughts. I hope they help you find the solution.
 
Ben
 

GeneralRe: Strong name vs URLmembergterziev1 Jul '05 - 4:40 
Ben, thanks for the replay,
 
I have found the solution in
http://www.dotnet247.com/247reference/msgs/18/92236.aspx
Namely, adding the attribute
[assembly: AllowPartiallyTrustedCallers()] in AssemblyInfo.cs of my Control has resolved the problem. Really I don't know exactly why. Not yet.
 
Georgi
GeneralUse with .ini filesmembertaylom23 Jun '05 - 4:02 
I am new to vb.net but have written apps in vb6 which run from a central server. However have tried both part 1 and 2 suggestions without success. The debugging routine always points to the line which accesses an ini file. This file lives in the same folder on the server as the .exe
 
I need to use ini files to allow other users to easily edit settings. The registry is not an option.
 
What else do I need to do?

GeneralRe: Use with .ini filesmemberkubben23 Jun '05 - 4:58 
I guess first I need to ask if you are working on your local pc? If you are then you need to double check the code group you set up. You probably have an error. You may not have set full trust. You might have not put a * in the network path name.
 
Now if it is working on your local PC, but not on a users PC. The issues I have seen are:
.net framework not loaded on a users PC. Load the .net framework.
They ran the MSI script, but it didn't add the code group. This usually happens when the user does not have admin rights to their own PC. Someone with admin rights must run the MSI script for them. You can use the RUNAS. I have also seen where after running the MSI script the User needs to log out and then log back in again.
 
I hope that is helpful.
 
Ben
GeneralRe: Use with .ini filesmembertaylom23 Jun '05 - 6:14 
thanks for the speedy reply
 
I cannot get it to work from a network drive back to my development laptop as well as to another client PC. All systems have the .net framework.
 
In the code group I used file://ip address/folder/* and also tried file://ip address/folder/applicationname.exe
 
I have full access to the network folder as I copy the .exe there.
 
I have double checked and full trust is set and I have admin rights on my laptop.
 
mike

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 7 Jun 2005
Article Copyright 2005 by kubben
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid