I am trying to publish to an ftp server. I am encrypting my Web.config file using this code:
var exeConfigName = #"D:\Repo\mypp\WebApplication1\Web.config";
Configuration config = ConfigurationManager.OpenExeConfiguration(exeConfigName);
var section = config.GetSection("appSettings") as AppSettingsSection;
ConnectionStringsSection section2 = config.GetSection("connectionStrings") as ConnectionStringsSection;;
var section3 = config.GetSection("system.net/mailSettings/smtp") as ConfigurationSection;
if (section != null && section.SectionInformation.IsProtected) {
// Remove encryption.
section.SectionInformation.UnprotectSection();
} else {
// Encrypt the section.
if (section != null) section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
}
if (section2 != null && section2.SectionInformation.IsProtected) {
// Remove encryption.
section2.SectionInformation.UnprotectSection();
} else {
// Encrypt the section.
if (section2 != null) section2.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
}
if (section3 != null && section3.SectionInformation.IsProtected) {
// Remove encryption.
section3.SectionInformation.UnprotectSection();
} else {
//Encrypt the section
if (section3 != null) section3.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
}
// Save the current configuration.
config.Save();
I get two webconfigs i.e Web.config(normal) and Web.config.cong(encrypted). When I publish only Web.config is shipped. So I manually added encrypted sections to the Web.config on server. But i get the following error:
Failed to decrypt using provider 'DataProtectionConfigurationProvider'. Error message from the provider: Key not valid for use in specified state.
</runtime>
<appSettings configProtectionProvider="DataProtectionConfigurationProvider">
<EncryptedData>//error highlighted in red
<CipherData>
<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAKvzpAGMd9EWXylxQjNCcdAQAAAACAAAAAAADZgAAwAAAABAAAABPSw54k9XlD+Mv/LWO9npqAAAAAASAAACgAAAAEAAAALpLRoKXjtupmwjCJCBfEtwgAAAAO3J95kdVtev2Cvc1Chtkajg8ZNamBU7zV9EXNy4VQgoUAAAAVNrkN3oVQVy12XSbxdZVVilA/r0=</CipherValue>
How can I fix this. Also i do not have a release folder in my bin folder(weird). This is my first time publishing and doing encryption. Thanks
Related
I am modifying my MyApp.vhost.exe, and the App.vhost.exe is modified as I can see in the text editor, but when I stop the debug application, the App.config values revert back to what they were before the change. What am I doing wrong or what am I missing?
Configuration exeConfiguration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var section = exeConfiguration.GetSection(monitorSectionElementName);
if (section != null)
{
var monitorPathElements = (section as MonitorSection).MonitorPaths;
monitorPathElements[monitorPath].CheckSum = checkSum;
}
exeConfiguration.Save(ConfigurationSaveMode.Full, true);
ConfigurationManager.RefreshSection(monitorSectionElementName);
With Advanced Installer, I'm trying to make a Custom Action, that at installationtime, encrypt the Connection String.
I seems like I can't use "~" here. (I moved my working code from the MVC project, to here).
Is there a simple alternative to that line or am I forced to make a complete rewrite and use e.g. a solution that uses somekind of Stream (like this Modifying Web.Config During Installation
Exception thrown by custom action:
System.Reflection.TargetInvocationException: Exception has been thrown by the
target of an invocation. ---> System.ArgumentException:
The application relative virtual path '~' is not allowed here.
Custom Action:
[CustomAction]
public static ActionResult EncryptConnStr(Session session)
{
try
{
var config = WebConfigurationManager.OpenWebConfiguration("~");
var section = (ConnectionStringsSection)config.GetSection("connectionStrings");
var cms = section.ConnectionStrings[GetConnectionStringName()];
var connStr = BuildConnStr(session["CONN_STR_SERVER"], session["CONN_STR_DATABASE"], session["CONN_STR_USERNAME"], session["CONN_STR_PASSWORD"]);
if (cms == null)
{
// Add new Connection String
section.ConnectionStrings.Add(new ConnectionStringSettings(GetConnectionStringName(), connStr));
}
else
{
// Update existing Connection String
cms.ConnectionString = connStr;
}
// Encrypt
section.SectionInformation.ProtectSection(ConnStrEncryptionKey);
// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);
return ActionResult.Success;
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace, ex.Message);
throw;
}
}
The solution to the path issue, is to use ConfigurationManager a long with some mapping, like this, instead of the web version WebConfigurationManager.
var map = new ExeConfigurationFileMap { ExeConfigFilename = path };
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
The encryption works fine as the code is, but the issue with save is still not solved because the execution time is to early. The installation isn't finished and the web.config isn't yet copyed to the APPDIR.
I am trying to encrypt sections of my web.config file through RSAProtectedConfigurationProvider programmatically. But at the time of encryption When it reach to SAVE(); It throws an exception System.Security.Cryptography.CryptographicException: Object already exists.
But if I encrypt it using DataProtectionConfigurationProvider it encrypts the section but when I run the application It gives
HTTP Error 500.23 - Internal Server Error
What could be the solution of it?
One more question I'm doing it all in SQLDataSource to read the connectionstring in the web.config file. Is this thing won't work if the web.config encrypted?
Here is my code :
private void ProtectSection(string sectionName, string provider)
{
CspParameters cspParams;
const int PROVIDER_RSA_FULL = 1;
const string CONTAINER_NAME = "NetFrameworkConfigurationKey";
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
CryptoKeyAccessRule rule = new CryptoKeyAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), CryptoKeyRights.FullControl, AccessControlType.Allow);
cspParams.CryptoKeySecurity = new CryptoKeySecurity();
cspParams.CryptoKeySecurity.SetAccessRule(rule);
Configuration config = WebConfigurationManager.openWebConfiguration(System.Web.HttpContext.Current.Request.ApplicationPath);
ConfigurationSection section = config.GetSection(sectionName);
if (section != null && !section.SectionInformation.IsProtected)
{
section.SectionInformation.ProtectSection(provider);
config.Save();
}
}
private void UnProtectSection(string sectionName)
{
Configuration config = WebConfigurationManager.openWebConfiguration(System.Web.HttpContext.Current.Request.ApplicationPath);
ConfigurationSection section = config.GetSection(sectionName);
if (section != null && section.SectionInformation.IsProtected)
{
section.SectionInformation.UnprotectSection();
config.Save();
}
}
Help Would Be much appreciated. THanks in Advance.
please find the below link which asks you give rights for the machine keys. Just give access for the iisuser / everyone and try the same. this works fine. The machine keys folder can be found in any one of the following folder
•\ProgramData\Microsoft\Crypto\RSA\MachineKeys
•\Users\All Users\Microsoft\Crypto\RSA\MachineKeys
Thank you
In our server, we configure the port in app.config as follows:
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp" port="1234" />
</channels>
</application>
</system.runtime.remoting>
</configuration>
We then proceed to configure the server with the following C# code:
RemotingConfiguration.Configure(string.Format("{0}{1}", appFolder, "app.exe.config"), false);
How do I reference the port number after it has been configured short of parsing the file by hand?
Looks like it is possible after all. After calling RemotingConfiguration.Configure(string, bool), I run the following method:
private string GetPortAsString()
{
// Parsing
System.Runtime.Remoting.Channels.IChannel[] channels = System.Runtime.Remoting.Channels.ChannelServices.RegisteredChannels;
foreach (System.Runtime.Remoting.Channels.IChannel c in channels)
{
System.Runtime.Remoting.Channels.Tcp.TcpChannel tcp = c as System.Runtime.Remoting.Channels.Tcp.TcpChannel;
if (tcp != null)
{
System.Runtime.Remoting.Channels.ChannelDataStore store = tcp.ChannelData as System.Runtime.Remoting.Channels.ChannelDataStore;
if (store != null)
{
foreach (string s in store.ChannelUris)
{
Uri uri = new Uri(s);
return uri.Port.ToString(); // There should only be one, and regardless the port should be the same even if there are others in this list.
}
}
}
}
return string.Empty;
}
This gives me the TcpChannel info I need, which allows me to grab the ChannelUri and get the port.
GRAIT SUCCESS!
You can only configure through code or configuration, you can't do both. This means you can't access the configured details via code, (without passing the xml file yourself).
I've just taken a look at the ConfigurationManager to help get the values you need...unfortunately it doesnt look like there is a sectionGroup for system.runtime.remoting: ie, this call fails:
var cfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var sectionGroup = cfg.GetSectionGroup("system.runtime.remoting");
So it doesn't appear to me you can use anything existing in the framework to extract it nicely. I'm unsure why this sectionGroup doesnt exist in-code.
How can I modify / manipulate the web.config programmatically with C# ? Can I use a configuration object, and, if yes, how can I load the web.config into a configuration object ? I would like to have a full example changing the connection string. After the modification the web.config should be written back to the harddisk.
Here it is some code:
var configuration = WebConfigurationManager.OpenWebConfiguration("~");
var section = (ConnectionStringsSection)configuration.GetSection("connectionStrings");
section.ConnectionStrings["MyConnectionString"].ConnectionString = "Data Source=...";
configuration.Save();
See more examples in this article, you may need to take a look to impersonation.
Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
ConnectionStringsSection section = config.GetSection("connectionStrings") as ConnectionStringsSection;
//section.SectionInformation.UnprotectSection();
section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
config.Save();
Since web.config file is xml file you can open web.config using xmldocument class. Get the node from that xml file that you want to update and then save xml file.
here is URL that explains in more detail how you can update web.config file programmatically.
http://patelshailesh.com/index.php/update-web-config-programmatically
Note: if you make any changes to web.config, ASP.NET detects that changes and it will reload your application(recycle application pool) and effect of that is data kept in Session, Application, and Cache will be lost (assuming session state is InProc and not using a state server or database).
This is a method that I use to update AppSettings, works for both web and desktop applications. If you need to edit connectionStrings you can get that value from System.Configuration.ConnectionStringSettings config = configFile.ConnectionStrings.ConnectionStrings["YourConnectionStringName"]; and then set a new value with config.ConnectionString = "your connection string";. Note that if you have any comments in the connectionStrings section in Web.Config these will be removed.
private void UpdateAppSettings(string key, string value)
{
System.Configuration.Configuration configFile = null;
if (System.Web.HttpContext.Current != null)
{
configFile =
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
}
else
{
configFile =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
}
var settings = configFile.AppSettings.Settings;
if (settings[key] == null)
{
settings.Add(key, value);
}
else
{
settings[key].Value = value;
}
configFile.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);
}