Computers, Programming, Technology, Music, Literature

Archive for the ‘C#’ Category

OWASP ZAP Development – Fixing the Can’t find bundle for base name lang.Messages error

leave a comment »

 

I have been generating the API files for OWASP ZAP DOT NET API since the inception. There is the core zaproxy project that has the DotNetAPIGenerator.java class. And there is the extensions project, including the beta and alpha.

image

Now, when I tried to generate the ‘non-optional’, i.e., the core API files for .Net, everything would work fine, the API files would be generated as below.

 

image

OWASP ZAP is internationalized, so the source code comes with a bunch of resource bundles with supporting language files.

When you try to generate the API files for the extensions project, you get this wonderful error message.

Exception in thread "main" java.util.MissingResourceException: Can’t find bundle for base name lang.Messages, locale en at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:1564) at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1387) at java.util.ResourceBundle.getBundle(ResourceBundle.java:890) at org.zaproxy.zap.extension.api.AbstractAPIGenerator.(AbstractAPIGenerator.java:68) at org.zaproxy.zap.extension.api.JavaAPIGenerator.(JavaAPIGenerator.java:81) at org.zaproxy.zap.extension.ApiGenerator.main(ApiGenerator.java:73)

 

image

I have fixed this error message before when I was trying to generate the api files back in 2015. Running in debug mode and stepping through pointed out that the zaproxy core project had the resource files under a directory that was not available to the extensions project.

This error was gruesome.

In the end all I had to do was copy the contents of the workspaceowaspzap\zaproxy\src\lang directory to workspaceowaspzap\zap-extensions\bin\lang

That’s it. Do the same thing for the alpha, and beta extensions’ bin directory too.

 

image

Cheers. Try the OWASP ZAP DOT NET API available at nuget.org.

Advertisements

Written by gmaran23

March 22, 2017 at 1:46 am

Beefing Up Security In ASP.NET Part 2 Dot Net Bangalore 4th meet up on August 08 2015

leave a comment »

Written by gmaran23

August 10, 2015 at 7:14 pm

SSIS – An Effortless Two Step Approach to Protect Sensitive Information in Xml Configuration Files

leave a comment »

 

I wanted to grab some text regarding DPAPI and RSA Encryption providers for my talk Beefing up Security in ASP.NET Part 2. But I couldn’t find it handy, I had to download a pdf version of this below SSISCipherBoy support guide. Posting here for easy access.

 

SSIS – An Effortless Two Step Approach to Protect Sensitive Information in Xml Configuration Files

 

I. Introduction

II. Competitive approaches

III. Prerequisites

IV. Preparing your package for configuration

V. Step 1 – Using SSISCipherBoy.exe – Select and encrypt configuration entries

VI. Step 2 – Using SSISCipherBoy.exe – Prepare the package to decrypt information

VII. Deploying package with encrypted configuration to server – Using SSISCipherBoy.exe – Export/Import RSA key pair

VIII. Common errors and debugging options

IX. What now?

X. Glossary

a. Using SSISCipherBoy.exe – Processing multiple packages sharing same config

b. Using SSISCipherBoy.exe – Dump SSISCipherUtil.dll to GAC / local directory

c. Manually installing SSISCipherUtil.dll to GAC

d. Manually create a ScriptTask to decrypt information

e. What does the automatic Package Processor do?

f. How does the cipher algorithm work?

XI. References and further reading

Acknowledgements

Writing a tool or an article becomes best when it is a communal effort. While I conceived and developed the library and tool, I want to acknowledge a few people who contributed in various ways.

Balabhadra Pavan Kumar, Dheeraj Dhamija, Balakrishna Allidi for constantly proving feedback, improvement aspects, and for reviewing sections of the support guide.

Manohara Mahadevappa for putting up with me during early development cycles and suggesting a bit of user friendly features.

Narasimha A Prakash, Sriram Seshan for being good enough to support me whenever I approached them.

I. Introduction

One of the ways of saving configuration entries for SSIS packages is an Xml configuration file, probably because they are simple editable text files, portable, and so on. When developing ASP.Net or Windows applications, most of us are cautious enough to encrypt the sensitive information that is saved in their configuration files. Reasons? May be it is thought that ASP.Net applications may reside on a web server that is exposed to outside world and hence they might be susceptible to attacks of sorts, and when that happens, we would not want to expose sensitive information in plain text, so we encrypt them. And the .Net framework provides it as an out-of-the-box functionality. In the most common scenarios that we have known, SSIS packages run as scheduled jobs inside a server that is located far inside the corporate firewall with ports closed, just sitting there in a good hope that ‘I am not vulnerable to attacks, so I can just be here with an xml configuration file that has connections strings, besides others things, in plain text’. As protection comes with security applied in various layers, the kind of attitude to rely on good hope and on firewall may just not be enough. In the wake of recent attacks in high profile organizations, if by any miracle, someone infiltrates and steals the data, we don’t want to expose further information in plain text. Do we? The risk could even come from a new developer that accidentally performs some unwanted activities on data (by using the information in the xml configuration file saved as plain text) that is meant to be protected from accidental damage, both foreign and domestic. That is the motivation to write this library and executable to help us encrypt information in our SSIS xml configuration files and hence this article. The entire process is done in two simple steps. If you are an experienced developer, read the prerequisites section and proceed directly to section V and VI.

II. Competitive approaches

That said, there are best practices that you can adhere to, like protecting the configuration using Access Control Lists that are tied to your Active Directory efforts, storing configurations in a SQL server database somewhere. Below are two blog entries that talk about our present options.

  1. SSIS: Storing passwords
  2. SSIS: Encrypted Configurations
  3. BI xPress Secure Configuration Manager

While there are pros and cons for approaches, they might not suit your need due to restrictions of company’s policies. And most developers prefer to encrypt and decrypt using a custom script task. While this is a viable option, it is a lot of effort to write a separate encryption module and unit test it, and not all developers are expert programmers that care about strong cryptography and key management. Most of the times the symmetric key used for encryption/decryption is hardcoded in the script task and the package itself is protected by a password. The encryption algorithm that the proposed library (referred to as SSISCipherUtil.dll from now on) uses state-of-the-art methods of encrypting information that hands over the cryptographic key management to the Windows operating system itself. As a matter of fact the ASP.Net out of the box functionality supports encrypting configuration information using DPAPI and RSA. SSISCipherUtil.dll comes with those two options. DPAPI associates cryptographic key with the windows user accounts and RSA uses key containers. That’s just a one liner. More at msdn – DPAPI, RSA.

When you have an encrypted configuration that you would like to be ported across multiple servers, use RSA, export the key pair from one server as xml, import it another server, then destroy the key pair xml file. If the package just sits on one server use RSA or DPAPI.

III. Prerequisites

1. Windows XP or later workstations, Windows Server 2003 or later server operating systems.

2. SSISCipherUtil.dll requires .Net framework 2.0 or later – is the library that helps in encryption/decryption during package setup and at package runtime.

3. SSISCipherBoy.exe requires .Net framework 3.5 or later – is the tool that helps you encrypt/decrypt a configuration entry at design time.

4. Auto code generation functionality of SSISCipherBoy.exe of requires a computer with Business Intelligence Development Studio (BIDS) installation.

5. Requires Administrator Privileges. Run as administrator option if UAC is switched on.

6. Supports only String encryption/decryption. No other data types are allowed.

7. Supports only Package.Variables and Package.Connections collections.

8. Supported Package ProtectionLevel values are DontSaveSensitive, EncryptAllWithPassword, EncryptSensitiveWithPassword. EncryptAllWithUserKey, EncryptSensitiveWithUserKey are supported only when the user account that modifies the package is used to run the package, in the same machine.

Below is the screenshot of the main window of SSISCipherboy.exe. Let’s explore the features one by one in later sections.

clip_image002

Fig. 3.1

IV. Preparing your package for configuration

If you here reading this article, I assume that you are an experienced developer that has configured and managed SSIS packages before. However, for the sake of completeness below are msdn references that explain saving SSIS configurations in xml files:

  1. Package Configurations
  2. Understanding Integration Services Package Configurations

Most important thing, if you don’t uncheck the Enable package configurations in SSIS Package Configurations Organize and if there is a configuration set up for the package, then the config files passed to the package using the /config option of dtexec.exe will not be effective. This might seem counter intuitive but that’s how SQL Server 2008 Integration Services works.

In the following steps, we will be running an unmodified package named AdvWrksLocalLoad2.dtsx with its original configuration AdvWrksLocalLoad2.dtsConfig, then run the modified package AdvWrksLocalLoad2-Mod.dtsx with an encrypted configuration AdvWrksLocalLoad2.dtsConfig, and then run the latter on a Windows 2008 R2 server (just like a production environment).

V. Step 1 – Using SSISCipherBoy.exe – Select and encrypt configuration entries

Now, without further delay, let’s pick a package and let’s encrypt its configuration entries. All the samples along with the tools are zipped and attached to this article. If someone’s interested in looking through the source code of SSISCipherBoy.exe and SSISCipherUtil.dll or enhancing its functionally or aesthetically, please contact me, I’d be pleased to share them.

Below is a list of files that we will be working with for demonstration.

clip_image004

Fig. 5.1

AdvWrksLocalLoad2.dtsx in Business Intelligence Development Studio is a package that does a few things, and the task the package performs is irrelevant here because we are concentrating on encrypting its configuration values in the xml configuration file. AdvWrksLocalLoad2.dtsx is protected with the password test [ProtectionLevel=EncryptAllWithPassword and PackagePassword=test].

clip_image006

Fig. 5.2

AdvWrksLocalLoad2.dtsConfig is the configuration file for AdvWrksLocalLoad2.dtsx that appears like below in Internet Explorer. As you could see the connection strings are mere plain text.

clip_image008

Fig. 5.3

Let’s encrypt them. Run SSISCipherBoy.exe as administrator. This program requires administrator privileges. On Windows systems with User Access Control (UAC) switched on, running as administrator is a mandatory requirement. Otherwise the program will not load properly; you will have to go to Task Manager to end it.

clip_image010

Fig. 5.4

When you run this program on a computer for the first time, it will install SSISCipherUtil.dll to the computer’s Global Assembly Cache (GAC).

clip_image012

Fig 5.5

Hit, OK to that warning, and proceed with the success message. Once the program is opened, let’s drag and drop the configuration file named AdvWrksLocalLoad2.dtsConfig. Use the Browse button to locate a configuration file if drag and drop does not work. The configuration file will be loaded in a tree view.

clip_image014

Fig. 5.6

Encrypting the values is as simple as selecting them and hitting the Encrypt button. However, if you pay attention to the third item, there is a User ID=EncrDemoUser, however, there is no Password provided for it in the configuration file. When you are exporting connections strings that contain a password, then SSIS Package Configurations Organizer does not export the Password property in the configuration file. It knows that a Password is sensitive information and it does not export the Password for ConnectionString. However, you could add it at your own risk – Just what we have been doing all along.

Before we do anything to this configuration file, lets test run it once.

dtexec.exe /file "C:\Maran\Project stuff\SSISCipherUtil\SSISCipher1.2.0.0\Demo\AdvWrksLocalLoad2.dtsx" /config "C:\Maran\Project stuff\SSISCipherUtil\SSISCipher1.2.0.0\Demo\AdvWrksLocalLoad2.dtsConfig" /DE test

clip_image016

Fig 5.7

The package runs just fine. Let’s get back to SSISCipherBoy.exe, right click on the item missing the Password property and click Edit Value to add a Password and hit the Save button.

clip_image018

Fig. 5.8


Note:
Nothing is saved to the original .dtsConfig file until you press the Commit changes to the config file button. Commit changes button gets enabled after the Encrypt/Decrypt buttons are clicked.

Once done, we have got two choices of encryption algorithm. To keep things simple: entries encrypted with DPAPI can only be decrypted on the computer on which it is encrypted on, however entries encrypted with RSA can be decrypted on any computer running windows if we export and import the key container used for encryption. So, if we encrypt a configuration entry on our development machine, in order to use the same configuration file across other environments, you will have to export and import the RSA key pair on the target machines using this tool SSISCipherUtil.exe. More about the algorithms are discussed in the Glossary section X-f.

Lets pick the entries that are sensitive, click the Lock/Unlock Selection button, provide a Key Container Name as myrsakey1 (you are free to provide any relevant name for the key container) and hit the Encrypt button. Wait for the success message, and now all the selected entries will be encrypted for you.

clip_image020

Fig. 5.9

Hit Commit changes to the config file button to save the encrypted data back to the file system.

clip_image022

Fig. 5.10

You may, try clicking the Lock/Unlock Selection button and try Encrypt/Decrypt/Edit Value and other operations; however until the time you click Commit changes to the config file, the changes that appear in the tree view will not be saved to the file system.

That’s it! You sensitive values are now encrypted. Next step is to prepare your package to decrypt the package at runtime. Don’t close the tool already; we will have to use it to generate decryption code.

clip_image024

Fig. 5.11

VI. Step 2 – Using SSISCipherBoy.exe – Prepare the package to ready to decrypt information

In our example, the package AdvWrksLocalLoad2.dtsx uses the configuration file AdvWrksLocalLoad2.dtsConfig. That is the configuration file that we encrypted in the preceding step. The dts runtime in no way knows that the configuration file is encrypted; neither there is a way we could tell it in a command line option. If you have DelayValidation=false (which is the default) in the package, then as soon as it encounters an invalid connection string (a connection string that does not have a name value pair like Initial Catalog, Server, User ID..), it throws exception saying that the validation failed and quits the execution of the job. Let’s see how to make a package ready to decrypt information during runtime.

As the AdvWrksLocalLoad2.dtsConfig is open in SSISCipherBoy.exe, check all the encrypted nodes, hit Lock/Unlock Selection and hit Generate decryption code button. This action displays a tip, hitting OK; brings you to the DecryptorCode window.

clip_image026

Fig. 6.1

clip_image028

Fig. 6.2

You are left with two options here.

#1. Manually create a ScriptTask to decrypt information

You can copy the decryption code from the right pane, create a ScriptTask before all other tasks in the target package and replace the scriptmain.cs code with the decryptor code and set the DelayValidation=true. If DelayValidation=false, then an error will be thrown because of invalid connection strings even before any of the tasks are executed. More about manually adding ScriptTask, at Glossary X-d.

#2. Make the package ready for decryption automatically

Drag and Drop a package in to the Package processor, click the Start Processing Below Packages button, and let the tool do the rest of the job for you. If Drag and Drop does not work double click on the package processor area to browse and pick a package. More about how it works, at Glossary X-e.

I am going to demonstrate option #2 here and if you are interested in option #1, refer to Glossary X-d.

With the Decryptorcode window open, add AdvWrksLocalLoad2.dtsx to the package processor and hit Start Processing Below Packages button. Hit OK to the big warning message. If the package is password protected, you will be prompted to enter a password. Enter the password as test and hit Done.


Note:
To process multiple package sharing same configuration file that was encrypted, refer to Glossary X-a.

clip_image030

Fig. 6.3

clip_image032

Fig. 6.4

clip_image034

Fig. 6.5

Accept the success message and close the tool. Let’s run the modified package with the encrypted configuration file. The modified package will be saved with a –Mod suffix.

dtexec.exe /file "C:\Maran\Project stuff\SSISCipherUtil\SSISCipher1.2.0.0\Demo\AdvWrksLocalLoad2-Mod.dtsx" /config "C:\Maran\Project stuff\SSISCipherUtil\SSISCipher1.2.0.0\Demo\AdvWrksLocalLoad2.dtsConfig" /DE test

The package runs as expected. It prints some base64 encoded strings to the command window, which can be neglected.

clip_image036

Fig. 6.6

That’s about it. Now lets try deploying the modfied package AdvWrksLocalLoad2-Mod.dtsx and the config file AdvWrksLocalLoad2.dtsConfig to a Windows 2008 R2 server and test run it.

VII. Deploying package with encrypted configuration to server – Using SSISCipherBoy.exe – Export/Import RSA key pair

As mentioned before, we can use the same encrypted configuration file on any other Windows workstations or servers.

  • You would need SSISCipherUtil.dll installed to the Global Assembly Cache (GAC) on the server. GAC is located at C:\Windows\assembly. You can drag and drop the SSISCipherUtil.dll to that folder. Or let the tool do that for you. If you could remember, when the SSISCipherBoy.exe runs for the first time on a computer, it aumatically installs SSISCipherUtil.dll to the GAC. Easiest option, let’s to that. Refer to the glossary X-b and X-c on how to install an assembly (dll) to GAC.
  • Importing the RSA key pair (that was used to encrypt the configuration) to the the server.


Note:
You can even use this tool to encryt and modify packages directly on an staging or production server, if you have done necessary testing in the development environments. The point is, if you want to use the same encrypted configuration file across all machines, then you would need to export/import the key container on all other machines.

I have logged on to a Windows server and copied the modified package – AdvWrksLocalLoad2-Mod.dtsx – and its config file – AdvWrksLocalLoad2.dtsConfig – to a location, SSISCipherBoy.exe on to my desktop. (You can place it anywhere though) (DTPOutput1.txt and Query.txt are files used by the package)

clip_image038

Fig. 7.1

1. Right click SSISCipherBoy.exe and select Run as administrator. Accept the User Access Control prompts, if any. SSISCipherUtil.dll will be automatically installed to the GAC, and the program loads fine.

clip_image040

Fig. 7.2

2. From our workstation, or from the development machine where we encrypted the configuration, let’s export the RSA key container named myrsakey1 and import it to the server. Open SSIScipherBoy.exe on your workstation or development machine (make sure to Run as administrator), provide the key container name that we used for encryption myrsakey1 and hit Export Rsa key pair. Save the file as myrsakey1.xml. And copy it to the server.

clip_image042

Fig. 7.3

Copy the myrsakey1.xml file to the server and use the Import Rsa key pair to import it. You should provide the same name myrsakey1 in the Key Container Name text box.

clip_image044

Fig. 7.4

After, successful import of RSA key pair, Destroy the file myrsakey1.xml and SSISCipherUtil.exe from the server.

That’s it! I am going to test run the package using the below command and you will see it working like it did in the development machine.

dtexec.exe /file "G:\Apps\SCOUT\Executables\ExpressNotice\AdvWrksLocalLostTest\AdvWrksLocalLoad2-Mod.dtsx" /config "G:\Apps\SCOUT\Executables\ExpressNotice\AdvWrksLocalLostTest\AdvWrksLocalLoad2.dtsConfig" /DE test

clip_image046

Fig. 7.5

VIII. Common errors and debugging options

  • If you get any CryptographicException during decryption, it is possible that

1. You are using DPAPI and trying to decrypt information on some other computer.

2. You are using RSA but you have not exported and imported the key pair (that was used to encrypt) yet.

3. The encrypted string is modified in some way or other and hence decryption failed.

  • If you get Connection Manager validations/runtime errors, it is possible that

1. Decryption failed

2. ConnectionString does not contain Password property

3. DelayValidation is set to false and you are getting an error because the ConnectionString property is encrypted. Since it is encrypted, it won’t contain strings like User ID, Password, Initial Catalog, Server etc., hence the validation error.

4. EnableConfiguration is set to true (i.e., Enable package configurations check box is checked in the Package Configuration Organizer wizard. And the design time associated configuration file is either missing or not encrypted).

  • To debug, the easiest way is to add a script task at the top of the package, and try accessing the Connection Manager’s ConnectionString property to see if values are getting decrypted properly. For instance, try logging them, or try a MessageBox.Show(). AdvWrksLocalLoad2.dtsx has a ScriptTask in the beginning that just alerts the ConnectionString values for a few connections.

clip_image048

Fig. 8.1

Or even better, add the package to a an Integration Services Project, set a break point on the ScriptTask and look if the values are getting set correctly.

  • If the Package Processor of DecryptorCode window throws any errors, close all Visual Studio instances, and try Start Processing Below Packages button again.
  • Rule of thumb, when running SSISCipherBoy.exe always Run as administrator.

IX. What now?

Hence you protect sensitive information in your SSIS Xml Config files. While the aforementioned methods describe an automated way of achieving encryption decryption, if any of the tasks fail, you could always try the manual lengthy process, or if you are interested in more information, the glossary section should suffice. Report any bugs, enhancement requests, set up assistance at https://renouncedthoughts.wordpress.com.

X. Glossary

a. Using SSISCipherBoy.exe – Processing multiple packages sharing same config

Under the heading “Step 2 – Using SSISCipherBoy.exe – Make the package ready to decrypt information” we saw how to process a package and make it ready for decryption. In that demonstration we added a package named AdvWrksLocalLoad2.dtsx that used a configuration named AdvWrksLocalLoad2.dtsConfig, which is a very common scenario. Another, common scenario is that we have one configuration file that will be shared by many packages. To make the job easier in these situations, the DecryptCode functionality allows you to add multiple packages to the Package Processor and process them all at one shot.

Let’s imagine that the configuration file named AdvWrksLocalLoad2.dtsConfig is used by multiple packages listed in the figure below.

clip_image050

Fig. a.1

In order to process them, Drag and drop all the packages or double click and select all the packages to the Package Processor of DecryptCode window; hit the Start Processing Below Packages button. Supply password if required, hit OK on the success message that appears after processing each package. If Drag and drop does not work double click and add multiple packages.

clip_image052

Fig. a.2

After processing, the processed packages are stored with a -Mod suffix on the same folder which looks like below.

clip_image054

Fig. a.3

b. Using SSISCipherBoy.exe – Dump SSISCipherUtil.dll to GAC / local directory

The encryption and decryption functionality is provided by the SSISCipherUtil.dll. The SSIS package in our example above that was modified to decrypt information at runtime, uses this dll. And the tool SSISCipherBoy.exe uses the same dll for all its primary operations. However, if you wanted to locate the SSISCipherUtil.dll in the file system, the only location you would find it is in the GAC. In case the assembly installation fails when the SSISCipherBoy.exe loads, you would be required to manually install the SSISCipherUtil.dll to GAC. Or when the package processor fails for some reason, you would want to create a Decryptor ScriptTask yourself manually. And when you create that Decryptor ScriptTask, you would need to Add a reference to the SSISCipherUtil.dll in Visual Studio in order to decrypt values at runtime. In order to accomplish any of these aforementioned tasks, you would need SSISCipherUtil.dll on some known file system location.

Run SSISCipherBoy.exe as administrator. Click the Assembly Administration … link at the top right corner.

clip_image056

Fig. b.1

clip_image058

Fig b.2

Use the buttons to perform the required operations.

c. Manually installing SSISCipherUtil.dll to GAC

Many might have observed that when adding a reference to a third party dll in a ScriptTask, we are bound to get AssemblyLoadException or FileNotFoundException if the referenced dll is not installed to the GAC. SSISCipherBoy.exe tries to install SSISCipherUtil.dll to the GAC at startup. If that does not work you can try installing it to the GAC using the Assembly Administration window. Remember that you need Administrator privileges to perform this task. So you run SSISCipherBoy.exe with administrator privileges at all times. If none of them works, the last resort is to emit the SSIScipherUtil.dll to a specific location and then manually install it to the GAC.

Installing to the GAC is simple.

1à Emit the SSISCipherUtil.dll to some file location (like explained in Glossary X-b)

2à Navigate to C:\Windows\assembly and Drag and Drop the SSISCipherUtil.dll to that folder C:\Windows\assembly. That’s it. You may also try to use the GacUtil.exe which is a program specifically meant for this purpose.

clip_image060

Fig. c.1

clip_image062

Fig. c.2

d. Manually create a ScriptTask to decrypt information

The package processor creates a ScriptTask inside a sequence container in the OnPreExecute EventHandler to decrypt information. If the Package Processor fails for some unknown reasons, you can try processing the package again or create a ScriptTask manually to decrypt information.

1à Create a ScriptTask on top of all other tasks in the Control Flow Tab of the Package Designer. Provide a relevant name.

Double click to open, hit the Edit Script button. Wait for the Visual Studio to load the project.

clip_image064

Fig. d.1

Add reference to the SSISCipherUtil.dll. (If you don’t have SSISCipherUtil.dll at you file system yet, use the Assembly Administration … link in SSISCipherBoy.exe and write the dll to some comfortable location – as in Glossary X-b)

clip_image066

Fig. d.2

4à Once the reference is added, replace the entire ScriptMain.cs code with the code from the DecryptorCode window of SSISCipherUtil.exe. Refer to the steps in Step 2 – Using SSISCipherBoy.exe – Make the package ready to decrypt information to copy the decryptor code.

Build the project; close the ScriptTask after successful build. Hit OK on the Script Task Editor. Save the dtsx package.

That completes everything, and now your package is modified to decrypt information at runtime. Let the ScriptTask and the SSISCipherUtil.dll do rest of the work for you.

e. What does the automatic Package Processor do?

When you add an SSIS package to the Package Processor of the DecryptorCode window, it does the following things:

  1. Tries to load the package at the specified location.
  2. If the package is protected with a password using EncryptAllWithPassword or EncryptSensitiveWithPassword, it prompts to enter the Password.
  3. On successful load of the package, it checks to see if there is an OnPreExecute EventHandler attached to this package.
  4. If an OnPreExecute EventHandler is attached to the package, it gets all the Tasks inside the OnPreExecute EventHandler and adds the DecryptionSequence on top of all those tasks.
  5. If an OnPreExecute EventHandler is not created for the package, it simply creates an OnPreExecute EventHandler and adds the DecryptionSequence to it.
  6. Inside the DecryptionSequence, there are two script tasks.
  7. First is a dummy ScriptTask that leads to the second ScriptTask that does the decryption.
  8. The decryption ScriptTask and the dummy ScriptTask are connected by a PrecedenceConstraint that allows the decryption ScriptTask to run only once during the execution of the package.

i.e., The decryption ScriptTask runs only during the OnPreExecute event of the package, when other tasks in the package fires an OnPreExecute event, the decryption ScriptTask is not called. This is done with the below Expression and Constraint check

@[System::SourceID]== @[System::PackageID]

  1. Sets DelayValidate=true for the package.
  2. Sets EnableConfiguration=false for the package. (the equivalent of un-checking Enable Package Configurations in Configuration wizard)

clip_image068

Fig. e.1

f. How does the cipher algorithm work?

SSISCipherUtil.dll supports DPAPI and RSA as we saw earlier. If you have a basic understanding of cryptography, please read forward, otherwise you may want to review the basics of Symmetric key cryptography, asymmetric key cryptography, and hashing. The following paragraphs are meant to give an overview of how DPAPI and RSA are implemented in SSISCipherUtil.dll. They might not depict the exact flow of how DPAPI and RSA work in SSISCipherUtil.dll. The source code is the only way to identify the exact implementation.

DPAPI

DPAPI – known as the Windows Data Protection API associates the cryptographic key used for encryption and decryption with the Windows User account and uses a machine wide key store. An application level entropy value is passed to the DPAPI method, so that only SSISCipherUtil.dll knows how to decrypt values that were encrypted by SSISCipherUtil.dll. The entropy value is an output of the Rfc2898DeriveBytes method that takes SHA-256 hash of some application wide constant values as input and salt.

RSA

RSA – an asymmetric cipher algorithm that in the .Net framework, not meant to encrypt inputs that are larger than the key size specified. In SSISCipherUtil.dll, the RSA algorithm is used to generate an exportable/importable public-private key pair stored at the RSA machine level key store. Later the public key components of the key pair are used to derive an entropy value, and the private key components are used to derive an input. The input and the entropy are later hashed with SHA-256 and sent to Rfc2898DeriveBytes. The output of Rfc2898DeriveBytes is used as a master key for RijndaelManaged algorithm which is a symmetric algorithm that works under the covers to encrypt and decrypt when using RSA.

C:\Users\All Users\Microsoft\Crypto\RSA\MachineKeys is the location in which the RSA key pairs are stored by Windows. That means, when you export/import an RSA key pair, the key pair with the specified key container name is accessed from this location.

References and Further Reading

1. SSIS: Storing Passwords – http://consultingblogs.emc.com/jamiethomson/archive/2007/04/26/SSIS_3A00_-Storing-passwords.aspx

2. SSIS: Encrypted Configurations – http://consultingblogs.emc.com/jamiethomson/archive/2007/05/04/SSIS_3A00_-Encrypted-Configurations.aspx

3. BI xPress Secure Configuration Manager – http://pragmaticworks.com/Products/BI-xPress/Features/SecureConfigurationManager.aspx

4. Understanding how SSIS configurations are applied – http://dougbert.com/blog/post/understand-how-ssis-package-configurations-are-applied.aspx

5. Integration Services Error and Message Reference – http://msdn.microsoft.com/en-us/library/ms345164.aspx

6. Dynamic Package Generation Samples – http://sqlsrvintegrationsrv.codeplex.com/releases/view/17647

7. Samples for creating SSIS packages programmatically – http://blogs.msdn.com/b/mattm/archive/2008/12/30/samples-for-creating-ssis-packages-programmatically.aspx

8. Programmatically recompiling a ScriptTask – http://social.msdn.microsoft.com/Forums/en/sqlintegrationservices/thread/27535ce7-c72c-4ea5-a27a-b34c12c73312

9. RSA class – http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsa.aspx

10. Windows Data Protection – http://msdn.microsoft.com/en-us/library/ms995355.aspx

11. CspKeyContainerInfo class – http://msdn.microsoft.com/en-us/library/system.security.cryptography.cspkeycontainerinfo.aspx

Written by gmaran23

August 8, 2015 at 8:50 pm

Programmatically encrypting sections in a web.config file

leave a comment »

 

During the talk “Beefing Up Security in ASP.NET – Part 2 at Dot Net Bangalore 4th meet up Aug 08 2015 “ someone asked how to encrypt web.config programmatically. Here’s an extract from a snippet I have used in the past. The below code should help you with the libraries you need to call, it is not complete, some parts of the code are removed. Copy & Paste may not work Sad smile

public static void EncryptConfigurationSection(string configurationSection)
{
    Configuration configurationFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    AppSettingsSection section = (AppSettingsSection)configurationFile.GetSection(configurationSection);

    if (!section.SectionInformation.IsProtected)
    {
        section.SectionInformation.ProtectSection("RSAProtectedConfigurationProvider");
        section.SectionInformation.ForceSave = true;
        config.Save(ConfigurationSaveMode.Full);
    }
}

 

 

Someone also asked if there is a way to specifically encrypt a particular attribute alone. I am afraid that is not possible out of the box. You could look at one of my RSCryptoServiceProvider implementation here to get started

https://ssiscipherboy.codeplex.com/SourceControl/latest#SSISCipherPackageSourceCode/SSISCipherUtil/AppCode/Cryptography/RSACipher.cs

Written by gmaran23

August 8, 2015 at 8:00 pm

Beefing Up Security In ASP.NET Dot Net Bangalore 3rd meet up on May 16 2015

leave a comment »

Let your IIS worker process crash with StackOverflowException

with one comment

 

This article was originally published for www.prowareness.com and could be located at http://www.prowareness.com/blog/let-your-iis-worker-process-crash-with-stackoverflowexception/

 

Months back I posted a screenshot at https://renouncedthoughts.wordpress.com/2013/12/05/system-stackoverflowexception-in-mscorlib-dll/, finally got time to write it down.

 

There was a Login page, that did some sort of authorization check beyond authenticating the user, and displayed an Access Denied page for those who weren’t lucky enough. This was all done by the ASP.NET MVC with ASPX view engine. So there’s things like Views, Partial Views, RenderPartial, and so on. The application also was heavily ajax enabled, so partial views really seemed to fit in at many places that did not want to include a master page content in the response text. There was a view file called AccessDenied.aspx that barked at unauthorized users. Things were working fine, and one day something broke, IIS was crashing without any meaningful error message. I lied, actually it did give a meaningful error message that was like – An unhandled exception of type ‘System.StackOverflowException’ occurred in mscorlib.dll. And the Call Stack showed some recursive function call. That is all there was to it.

Let’s look at a POC sample application below. Download the source from github – https://github.com/gmaran23/ASPXViewEngineCrash, Hit F5.

 

clip_image002[11]

 

When you click the AccessDeniedForCrash page, the below is what you see. An unhandled exception of type ‘System.StackOverflowException’ occurred in mscorlib.dll. If you look at the Call Stack window, there would be a lot of repeated method calling method.

 

clip_image002[13]

 

Let’s look at what happens when a view is requested, as in how the view engine probes the known locations to find the view definition. Click ViewDoesNotExist, and you would see an error page, that actually tells you the file locations that ASPX view engine probed to find a matching view. Pay attention to the search order where a .aspx file is searched first, and then the .ascx file.

clip_image002[15]

Now, if you go back to the StackOverflowExceptionInASPXViewEngine solution, there are two files called AccessDeniedForCrash.ascx and AccessDeniedForCrash.aspx under ~/Views/Home.

 

clip_image002[19]

 

The following code inside AccessDeniedForCrash.aspx calls the partial view AccessDeniedForCrash.ascx.

 

<asp:Content ID="Content3" ContentPlaceHolderID="FeaturedContent" runat="server">
            <section class="featured">
        <div class="content-wrapper">
            <hgroup class="title">
                <% Html.RenderPartial("AccessDeniedForCrash"); %>
            </hgroup>
        </div>
    </section>
</asp:Content>

 

A typical programming practice right? You define sub routines, and you keep calling them as and when required. Reusability! You have created a partial view here (AccessDeniedForCrash.ascx), and kept calling the partial view inside the main view (AccessDeniedForCrash.aspx). But it was the ASPX view engine’s probing method that caused the recursive method call. The view engine reached AccessDeniedForCrash.aspx, as it came through the HomeController’s action method AccessDeniedForCrash. It tried to find a partial view AccessDeniedForCrash.ascx,  but always ended up with AccessDeniedForCrash.aspx because of the file search order; you know the rest of the story about recursion without an exit condition.

So, is this a programming error? or the framework error? or the ‘programmer did not understand the framework well’ error?

 

 

You may also like – https://renouncedthoughts.wordpress.com/2013/12/05/system-stackoverflowexception-in-mscorlib-dll/

Written by gmaran23

June 30, 2014 at 7:16 pm

Access Control through ASP.Net MVC Custom Action Filters

leave a comment »

 

A slightly different version of this article was originally published for www.prowareness.com and could be located at http://www.prowareness.com/blog/access-control-through-asp-net-mvc-custom-action-filters/

HttpModule being the gatekeeper ASP.Net, one level down is the Action Filters for ASP.Net MVC. While managing large scale applications, it would not always seem very rational to create new Controllers for every functionality sometimes. You may also want to restrict access to specific controllers or specific action methods, and if you worked it through you would end up with a code snipped like below. An if else condition everywhere you wanted access control.

        [HttpGet]
        public ActionResult CustomizeEmails()
        {
            if (Context.Login.IsAdministrator)
            {
                var viewModel = new CustomizeEmailViewModel();
                return View(viewModel);
            }
            else
            {
                return AccessDeniedView();
            }
        }

        [HttpGet]
        public ActionResult CustomizeUserHomePage()
        {
            if (Context.Login.IsAdministrator)
            {
                var viewModel = new CustomizeUserHomePageViewModel();
                return View(viewModel);
            }
            else
            {
                return AccessDeniedView();
            }
        }


Which is obviously redundant and does not reflect on code reusability principle. So you may choose to create a custom HttpModule for access control during the initial ASP.Net request pipeline, of if that is not a possible solution in your case (or like the one above in ASP.Net MVC), then you must be looking at building a custom action filter. Once you have that in place, you could decorate your required action methods with your access control custom filter, or the entire controller, or as a global action filter (post ASP.Net MVC 3) so that the action filter would get invoked on every controller in the application.

Below is the code snippet showing the bare minimal implementation of a custom action filter for access control. In case the current request does not come from an Administrator, then it redirects him to an AccessDenied action method in the CompanyController.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebClient.Filters
{
    public class AdminOnlyAction : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //Cast the filterContext.Controller to the controller that has the access control information 
            //In my case it happened to be a BaseController
            var baseController = ((BaseController)filterContext.Controller);

            if (!baseController.Context.Login.IsAdministrator)
            {
                filterContext
                    .HttpContext
                    .Response
                    .RedirectToRoute(new { controller = "Company", action = "AccessDenied" });
            }

            base.OnActionExecuting(filterContext);
        }
    }
}

 

The if else statements in the first snippets would take a little more elegant, and neat form.

        [HttpGet]
        [AdminOnlyAction]
        public ActionResult CustomizeEmails()
        {
                var viewModel = new CustomizeEmailViewModel();
                return View(viewModel);
        }

        [HttpGet]
        [AdminOnlyAction]
        public ActionResult CustomizeUserHomePage()
        {
                var viewModel = new CustomizeUserHomePageViewModel();
                return View(viewModel);
        }


Thus you would have a simple, elegant, and powerful access control mechanism via a custom action filter. If you like this kind of cleanliness in non MVC projects, please take a look at POSTSHARP as well.

Written by gmaran23

March 12, 2014 at 8:11 pm

TPL – And that’s why it’s called Cooperative Cancellation

leave a comment »

 

This article was originally published for www.prowareness.com and could be located at http://www.prowareness.com/blog/tpl-and-thats-why-its-called-cooperative-cancellation/

 

It’s a practice to provide a Cancel button to a ‘tired of waiting’ user for a long running operation. In WinForms, you would probably create a BackgroundWorker or a separate thread to keep the UI responsive to the user can click the Cancel button. When the user clicks the Cancel button, how you actually implement the cancellation logic is the topic of this blog.

Please read Interrupt Politely, to get a complete overview of the cancellation options. Now, let’s get in to the types introduced with .Net 4.0 and what TPL has to offer.

The CalculateSum method below is our long running operation, that does nothing but adds a couple of numbers; keeps us posted on the calculated value via Console.WriteLine and sleeps on a condition.

        static void CalculateSum(Int64 loopThreshold)
        {
            UInt64 sum = 0;

            for (Int16 i = 0; i < Int16.MaxValue; i++)
            {
                sum += Convert.ToUInt64(i);

                if (i % 100 == 0) //go to pit, take some rest
                {
                    Console.WriteLine(Environment.NewLine + "{0}, Intermediate Sum value {1}", MethodInfo.GetCurrentMethod().Name, sum);
                    Thread.Sleep(1000); //waste time to simulate work
                }
            }

            Console.WriteLine(sum);
        }

 

The method CallerWithoutCancellation calls the above CalculateSum method via a Task.

        static void CallerWithoutCancellation()
        {
            var task = Task.Factory.StartNew(() =>
                {
                    CalculateSum(Int16.MaxValue);
                }
            );
        }

 

Imagine, if the user wanted to cancel this long running task, there is no provision for cancellation that the method CalculateSum provides. If you ran CalculateSum with a classic Thread as opposed to a Task, then you would either issue a Thread.Abort or Thread.Interrupt. This is a decision you have to make carefully. Option 1 in the drdobbs journal and Aborting and Interrupting Threads talk more about them.

But with Task Parallel Library, CancellationTokenSource and CancellationToken, we have better options to cancel.

Let’s look at the implementation of the CalculateSum method with a new overload taking a CancellationToken parameter named inputCancellationToken. Pay careful attention to the line inputCancellationToken.ThrowIfCancellationRequested().

 

        static void CalculateSum(CancellationToken inputCancellationToken, Int16 loopThreshold)
        {
            UInt64 sum = 0;

            for (Int16 i=0; i < loopThreshold; i++)
            {
                sum += Convert.ToUInt64(i);

                if (i % 100 == 0) //go to pit, take some rest
                {
                    Console.WriteLine(Environment.NewLine + "{0}, Intermediate Sum value {1}", MethodInfo.GetCurrentMethod().Name, sum);

                    inputCancellationToken.ThrowIfCancellationRequested(); //accept and honor the cancellation request

                    Thread.Sleep(1000); //waste time to simulate work
                }
            }

            Console.WriteLine(Environment.NewLine + "{0}, Final Sum value {1}", MethodInfo.GetCurrentMethod().Name, sum);
        }

 

The caller, CallerWithCancellationToken, has a cancellation option on press of the Enter key; then it calls cancellationTokenSource.Cancel(). Also pay attention to the second parameter cancellationToken in the Task.Factory.StartNew method.

 

        static void CallerWithCancellation()
        {
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            CancellationToken cancellationToken = cancellationTokenSource.Token;

            var task = Task.Factory.StartNew(() => {
                try
                {
                    CalculateSum2(cancellationToken, Int16.MaxValue);
                }
                catch (Exception ex)
                {
                    Console.Write(Environment.NewLine + ex.GetType().ToString() + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace);
                    throw;
                }
            }, cancellationToken);

            Console.WriteLine(Environment.NewLine + "{0}, ********** Press Enter to cancel the running task **********", MethodInfo.GetCurrentMethod().Name);

            Thread.Sleep(2000); //rest sometime while the task runs

            Console.ReadLine();
            Console.WriteLine(Environment.NewLine + "{0}, ---------- Issuing a cancellation request ----------", MethodInfo.GetCurrentMethod().Name);
            cancellationTokenSource.Cancel(); //issue a cancellation request
            Console.WriteLine(Environment.NewLine + "{0}, ---------- Cancellation request issued ----------", MethodInfo.GetCurrentMethod().Name);
        }

 

The CalculateSum method provides a provision for cancellation using the CancellationToken and the CallerWithCancellation method requests for a cancellation via the same CancellationToken.

As an alternative, you could also poll on the IsCancellationRequested property and proceed with clean up and cancellation.

        static void CalculateSum2(CancellationToken inputCancellationToken, Int16 loopThreshold)
        {
            UInt64 sum = 0;

            for (Int16 i = 0; i < loopThreshold; i++)
            {
                sum += Convert.ToUInt64(i);

                if (i % 100 == 0) 
                {
                    Console.WriteLine(Environment.NewLine + "{0}, Intermediate Sum value {1}", MethodInfo.GetCurrentMethod().Name, sum);

                    if (inputCancellationToken.IsCancellationRequested) //accept and honor the cancellation request
                    {
                        //cleanse if required
                        Console.WriteLine(Environment.NewLine + "{0}, ---------- Cooperating with the cancellation request and exiting ----------", MethodInfo.GetCurrentMethod().Name);
                        return;
                    }

                    Thread.Sleep(1000); //waste time to simulate work
                }
            }

            Console.WriteLine(Environment.NewLine + "{0}, Final Sum value {1}", MethodInfo.GetCurrentMethod().Name, sum);
        }

 

What you effectively have here is a mechanism where the caller signals for a cancellation request via cancellationTokenSource.Cancel(), and the callee responds to it by cancelling itself via inputCancellationToken.ThrowIfCancellationRequested() or performing necessary clean up operations by checking inputCancellationToken.IsCancellationRequested.

 

image

Now, you see a coordination, an agreement between the caller and the callee, or in other words, they both cooperated for cancellation. And that’s why it’s called Cooperative Cancellation.

 

Download and play the source code here.

Note: This pattern existed way before TPL, but you had to rely on synchronization mechanism when reading or writing the cancellation flag. Now with TPL, it is build in with the CancellationTokenSource and CancellationToken.

Written by gmaran23

October 25, 2013 at 7:36 pm

Writing @helper like inline helper method for ASPX view engine

leave a comment »

 

This article was originally published for www.prowareness.com and could be located at http://www.prowareness.com/blog/writing-helper-like-inline-helper-method-for-aspx-view-engine/

When I started my MVC course with ASP.NET MVC 3, I got introduced to the @helper syntax with the Razor view engine. In case you didn’t know what an @helper syntax is, you may read more about it here. It is common that during training sessions, certain features of a technology may not appeal to you until you really use it, or until you have someone who puts that in perspective for you. So, I was dealing with an MVC application with ASPX view engine and I had a situation where I thought if I had Razor view engine, I could use the @helper syntax, and here’s what I ended up with.

 

The @helper syntax within Razor enables you to easily create re-usable helper methods that can encapsulate output functionality within your view templates.  They enable better code reuse, and can also facilitate more readable code. – Source

 

In this post, I will show you can write a Razor style @helper method for ASPX view engine. Some people like to call it the Inline helper method If you look at the end result of the helper method in Razor view engine and ASPX view engine, it not aesthetically similar or lucid, but it solves the purpose – you get re-usability within the view. There are alternative ways of achieving the same thing using a Html helper of a server method within the view, but I ended with this approach.

In the ASPX view engine, if you declare and initialize a variable, if would show up in the intelli-sense. In the same way, if you try declaring an Action delegate, it would show up in the intelli-sense.

 

image

 

And that’s the trick. Declare an Action delegate, initialize with an anonymous delegate. You are done.

    <% 
        Action<int> DisplayPrice2 = (price) =>
        {
            if (price < 5)
            {%>
    <span>FREE!</span>
    <%}
            else
            {%>
    <%: String.Format("{0:C2}", price)%>
    <%}
            };            
    %>

    <h2>Products (ASPX View Engine - with inline helper)</h2>
    <%foreach (var product in Model)
      {%>
    <li>
        <span class="producttitle">
            <%: product.Name %>
        </span>
        <span class="description">
            <%: product.Description%>
        </span>
        <span class="price">
            <% DisplayPrice2(product.Price); %>
        </span>
    </li>
    <%} %>

 

Note that when you initialize the Action delegate, you could either use the explicit delegate keyword or just a lambda.

Download: Sample projects including the source code for @helper sample in Razor view engine, and the Action delegate way of doing it in the ASPX view engine is downloadable at the SkyDrive location – http://sdrv.ms/15ykUXD

Written by gmaran23

September 27, 2013 at 6:19 pm

Posted in .Net, Asp.Net MVC, C#

Tagged with , ,

Incorrect MSDN documentation: The space after Global:: should be removed

leave a comment »

 

Code sample posted at http://msdn.microsoft.com/en-us/library/ms228766(v=vs.100).aspx would not work and would yield you an ArgumentException with an error message as below:

Error message:

System.ArgumentException

The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))

   at EnvDTE.Command.set_Bindings(Object pVar)

 

Fix:

Fix it by removing the extra space after Global::

Code in the sample above should be changed to

//Notice there is no space after Global::
bindings[0] = "Global::CTRL+SHIFT+ALT+Y"; 
bindings[1] = "Global::CTRL+SHIFT+ALT+X"; 

 

Three hours for a triviality. Nothing unusual.

Related Links:

  1. Binding Add-In Commands to Keys – http://msdn.microsoft.com/en-us/library/5x1f46hd(v=vs.100).aspx 
  2. Visual Studio Add in Error Number 80070057 – http://www.codeproject.com/Articles/463969/Visual-Studio-Add-in-Error-Numbers-Troubleshooting#80070057

Written by gmaran23

August 27, 2013 at 7:45 pm