security problems using getprivateprofilestring api call to read ini file over network

I'm attempting to use the GetPrivateProfileString API call to read from an INI file.  (Note - This is my first venture into .NET development and I understand .config files are the current thing, but I already had code which did what I wanted with an INI file, so I thought it would be a faster development path...)
When my test application resides on the desktop from which I'm running it, everything works fine (ie. start | run | c:\projects\testapp.exe).  However, I need to be able to deploy the application on a network server and call it from various places within our corporate intranet.  This is where the trouble began.

The error I'm receiving reads as follows:
"An unhandled exception of type 'System.Security.SecurityException' occurred in testapp.exe

Additional information: System.Security.Permissions.SecurityPermission"


After spending an entire day frantically reading everything I could find which related to this error, I did the following:

-Created a strong name for my assembly using sn.exe, and used caspol.exe -af testapp.exe to add the assembly to the Full Trust list.

caspol -rsg testapp.exe now returns:
Microsoft (R) .NET Framework CasPol 1.1.4322.573
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.


Level = Enterprise

Code Groups:

1.  All code: FullTrust


Level = Machine

Code Groups:

1.  All code: Nothing
   1.1.  Zone - MyComputer: FullTrust
   1.8.  StrongName - 0024000004800000940000000602000000240000525341310004000001000100B96A79416CFB6D1FBCB8D219D9CF0361F66653BB0E6B2FC1E5223343B722516F0F24537E69AE618D076AC22AE1B8BC354195E8520C4A530C2B8D6ED59A3A3C379411CABCF53D5E3C53506950965CE953B85C7E035FB596ADAABB21BAA49921958088664144ABA988FD3CF7E5C30AFC06BCDF542F7E3CF77088F189D6EC17E2C0 version = 1.0.2097.26735: FullTrust (LevelFinal)


Level = User

Code Groups:

1.  All code: FullTrust

Success

and caspol -rsp testapp.exe returns
Microsoft (R) .NET Framework CasPol 1.1.4322.573
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

Resolving permissions for level = Enterprise
Resolving permissions for level = Machine
Resolving permissions for level = User

Grant =
<PermissionSet class="System.Security.PermissionSet"
               version="1"
               Unrestricted="true">
   <IPermission class="System.Security.Permissions.StrongNameIdentityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                version="1"
                PublicKeyBlob="0024000004800000940000000602000000240000525341310004000001000100B96A79416CFB6D1FBCB8D219D9CF0361F66653BB0E6B2FC1E5223343B722516F0F24537E69AE618D076AC22AE1B8BC354195E8520C4A530C2B8D6ED59A3A3C379411CABCF53D5E3C53506950965CE953B85C7E035FB596ADAABB21BAA49921958088664144ABA988FD3CF7E5C30AFC06BCDF542F7E3CF77088F189D6EC17E2C0"
                Name="testapp"
                AssemblyVersion="1.0.2097.26735"/>
   <IPermission class="System.Security.Permissions.UrlIdentityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                version="1"
                Url="
file://F:/trusted/testapp/testapp.exe"/>
   <IPermission class="System.Security.Permissions.ZoneIdentityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                version="1"
                Zone="MyComputer"/>
</PermissionSet>

Success

-
Finally I attempted to disable code access security entirely with caspol -s, but I still have the same error in the same spot.

-On the application end, I created SecurityPermission objects with SecurityPermissionFlag.UnmanagedCode, and then when that didn't work, .AllFlags values everywhere I thought they could possibly be relevant.  I used .Assert because from what I read, this was the least restrictive and most potent permission available.
The function which makes the GetPrivateProfileString API call is as follows:

Public Function GetString(ByVal Section As String, _
ByVal Key As String, ByVal [Default] As String) As String

Dim oSecPerm As New SecurityPermission(SecurityPermissionFlag.AllFlags)oSecPerm.Assert()
Dim intCharCount As
Integer
Dim objResult As New
System.Text.StringBuilder(256)
intCharCount = GetPrivateProfileString(Section, Key, _
[Default], objResult, objResult.Capacity, strFilename)

If intCharCount > 0 Then GetString = Left(objResult.ToString, intCharCount)

End Function

This function is called right at the start of the app, near the beginning of Sub Main, as shown below (note again the use of SecurityPermission objects):

Function Main(ByVal CmdArgs() As String) As Integer
Dim ArgNum As Integer
' Index of individual command-line argument.
Dim strCurrentArg As
String
Dim bSetup As Boolean =
True
'retrieve .ini file entries if any (file is assumed to be in same directory as exe)
'does it exist
'Try
gstrINIPath = Application.StartupPath & "\testapp.ini"

If File.Exists(gstrINIPath) = True Then

Dim oINIFile As New AUINIFile(gstrINIPath)
Dim oSecPerm As New
SecurityPermission(SecurityPermissionFlag.AllFlags)
oSecPerm.Assert()

gstrSQLServerName = oINIFile.GetString("testapp", "SQLServerName", "")


This last line is where the error occurs, and continues to occur, despite everything I've attempted above.  I am going to look at using .config file instead, but I need to know why this doesn't work, because it will probably be other similar problems...

Any assistance would be greatly appreciated!

Jim.



Answer this question

security problems using getprivateprofilestring api call to read ini file over network

  • Jason Rieger

    Right -- that's an important clarification to make.  CAS evaluation occurs on the machine that executes the code, not on the machine that supplies the code.  (Although the machine that supplies the assembly can help the executing machine determine what permissions to grant based upon its identity).

    -Shawn



  • Ali Shahzad

    Hi Jim,

    You've run into My application works from my local machine, but throws a SecurityException when I move it to a network share.  As you've seen you can't use Assert to cause yourself to have more permissions then when you started (See Assert Myths #1, 3, and 7) -- if you could, then that would be a pretty large security hole Smile.

    -Shawn



  • machan

    Thank you, Shawn, for your quick response.  This appears to be moving me quickly in the right direction.  I would like to try to understand a little more clearly the difference between the policy change I made as directed by your reference to "My application works from my local machine..." above vs. the policy change I originally made, which involved adding my assembly's strong name to the full trust list.  If I understand the reference article correctly, by creating a new child code group for my assembly under the All Code parent group and giving it the Strong Name membership condition and the Full Trust permission set, I'm saying to the policy, "trust all code for this assembly on this machine, regardless of which other code group (My Computer, Local_IntranetZone, etc.) it may be associated with."  Is this more or less correct

    Thanks,

    Jim.


  • Carlos Magalhaes

    You're saying:

    "All code with this strong name, should be granted FullTrust".  Then, when the CLR finds the LocalIntranet group it says "All code on a network share should get LocalIntranet."

    So now we have two permission sets that are to be assigned to the code.  Since the AllCode code group (which is the parent of both the strong name and the LocalIntranet group) is a UnionCodeGroup, we union them together:

    LocalIntranet Union FullTrust = FullTrust

    As for why this is different from the caspol -af you used earlier: see What's the FullTrust List for Anyway

    -Shawn



  • graphex

    Shawn, could you elaborate on your statement "Although the machine that supplies the assembly can help the executing machine determine what permissions to grant based upon its identity"   Is it possible for the machine supplying the code to provide sufficient information to negate the need for the machine executing the code to have a specific permission set created   This would definitely simplify deployment!

    Jim.

  • Devendra Chandola

    Again, thanks for the clarification, Shawn.  That makes sense and corresponds with the behaviour I've seen.  I was eventually able to get my application working.  I misunderstood initially that the Full Trust permission set for my assembly's strong name needed to be created on EACH WORKSTATION accessing the assembly, rather than on the server providing the assembly.  The .NET Framework installed on an individual desktop is determining what can and cannot be run within it's context, and so it requires that specific permission set to make it's decision in favour of the "foreign" assembly coming in from the server.
  • security problems using getprivateprofilestring api call to read ini file over network