private void EditMI_Click(object sender, EventArgs e) { try { FileSystemAccessRule fileSystemRule = SelectedTag as FileSystemAccessRule; ApplicationAccessRule applicationRule = SelectedTag as ApplicationAccessRule; if (fileSystemRule == null && applicationRule == null) { return; } if (fileSystemRule != null) { applicationRule = new ApplicationAccessRule(); applicationRule.RuleType = ApplicationAccessRule.Convert(fileSystemRule.AccessControlType); applicationRule.Right = GetEffectiveRight(fileSystemRule); applicationRule.IdentityReference = fileSystemRule.IdentityReference; } if (!new AccessRuleDlg().ShowDialog(applicationRule)) { return; } UpdateItem(ItemsLV.SelectedItems[0], applicationRule); AdjustColumns(); } catch (Exception exception) { GuiUtils.HandleException(this.Text, System.Reflection.MethodBase.GetCurrentMethod(), exception); } }
/// <summary> /// Displays the dialog. /// </summary> public bool ShowDialog(ApplicationAccessRule accessRule) { AccessTypeCB.SelectedItem = accessRule.RuleType; IdentityNameTB.Text = accessRule.IdentityName; m_identity = accessRule.IdentityReference; if (m_identity == null) { AccountInfo account = AccountInfo.Create(IdentityNameTB.Text); if (account != null) { m_identity = account.GetIdentityReference(); } } if (accessRule.Right != ApplicationAccessRight.None) { AccessRightCB.SelectedItem = accessRule.Right; } if (ShowDialog() != DialogResult.OK) { return false; } accessRule.RuleType = (AccessControlType)AccessTypeCB.SelectedItem; accessRule.Right = (ApplicationAccessRight)AccessRightCB.SelectedItem; accessRule.IdentityReference = m_identity; return true; }
/// <summary> /// Updates an item in the control. /// </summary> protected override void UpdateItem(ListViewItem listItem, object item) { FileSystemAccessRule fileSystemRule = item as FileSystemAccessRule; ApplicationAccessRule applicationRule = item as ApplicationAccessRule; if (fileSystemRule == null && applicationRule == null) { base.UpdateItem(listItem, item); return; } if (fileSystemRule != null) { listItem.SubItems[0].Text = fileSystemRule.AccessControlType.ToString(); listItem.SubItems[1].Text = fileSystemRule.IdentityReference.Value; listItem.SubItems[2].Text = GetEffectiveRight(fileSystemRule).ToString(); listItem.SubItems[3].Text = GetRightsForFile(fileSystemRule.FileSystemRights); listItem.SubItems[4].Text = (fileSystemRule.IsInherited)?"Yes":"No"; listItem.ImageKey = (fileSystemRule.AccessControlType == System.Security.AccessControl.AccessControlType.Allow) ? GuiUtils.Icons.Users : GuiUtils.Icons.UsersRedCross; } if (applicationRule != null) { listItem.SubItems[0].Text = applicationRule.RuleType.ToString(); listItem.SubItems[1].Text = applicationRule.IdentityName; listItem.SubItems[2].Text = applicationRule.Right.ToString(); listItem.SubItems[3].Text = null; listItem.SubItems[4].Text = null; listItem.ImageKey = (applicationRule.RuleType == AccessControlType.Allow) ? GuiUtils.Icons.Users : GuiUtils.Icons.UsersRedCross; } listItem.Tag = item; }
/// <summary> /// Gets the log file directory and ensures it is writeable. /// </summary> public static string GetLogFileDirectory() { // try the program data directory. string logFileDirectory = ApplicationData.Current.LocalFolder.Path; logFileDirectory += "\\OPC Foundation\\Logs"; try { // create the directory. if (!Directory.Exists(logFileDirectory)) { Directory.CreateDirectory(logFileDirectory); } // ensure everyone has write access to it. List <ApplicationAccessRule> rules = new List <ApplicationAccessRule>(); ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Users; rule.Right = ApplicationAccessRight.Configure; rule.RuleType = AccessControlType.Allow; rules.Add(rule); rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.NetworkService; rule.Right = ApplicationAccessRight.Configure; rule.RuleType = AccessControlType.Allow; rules.Add(rule); rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.LocalService; rule.Right = ApplicationAccessRight.Configure; rule.RuleType = AccessControlType.Allow; rules.Add(rule); ApplicationAccessRule.SetAccessRules(logFileDirectory, rules, false); } catch (Exception) { // try the MyDocuments directory instead. logFileDirectory = ApplicationData.Current.LocalFolder.Path; logFileDirectory += "OPC Foundation\\Logs"; if (!Directory.Exists(logFileDirectory)) { Directory.CreateDirectory(logFileDirectory); } } return(logFileDirectory); }
/// <summary> /// Gets the log file directory and ensures it is writeable. /// </summary> public static string GetLogFileDirectory() { // try the program data directory. string logFileDirectory = ApplicationData.Current.LocalFolder.Path; logFileDirectory += "\\OPC Foundation\\Logs"; try { // create the directory. if (!Directory.Exists(logFileDirectory)) { Directory.CreateDirectory(logFileDirectory); } // ensure everyone has write access to it. List<ApplicationAccessRule> rules = new List<ApplicationAccessRule>(); ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Users; rule.Right = ApplicationAccessRight.Configure; rule.RuleType = AccessControlType.Allow; rules.Add(rule); rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.NetworkService; rule.Right = ApplicationAccessRight.Configure; rule.RuleType = AccessControlType.Allow; rules.Add(rule); rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.LocalService; rule.Right = ApplicationAccessRight.Configure; rule.RuleType = AccessControlType.Allow; rules.Add(rule); ApplicationAccessRule.SetAccessRules(logFileDirectory, rules, false); } catch (Exception) { // try the MyDocuments directory instead. logFileDirectory = ApplicationData.Current.LocalFolder.Path; logFileDirectory += "OPC Foundation\\Logs"; if (!Directory.Exists(logFileDirectory)) { Directory.CreateDirectory(logFileDirectory); } } return logFileDirectory; }
/// <summary> /// Extracts the access rules from the SDDL string. /// </summary> private static void ParseSddl(string url, string sddl, List <HttpAccessRule> accessRules) { IList <AccessControlEntity> entities = AccessControlEntity.Parse(sddl); for (int ii = 0; ii < entities.Count; ii++) { AccessControlEntity entity = entities[ii]; if (entity.AccessType != "A") { continue; } ApplicationAccessRight rights = ApplicationAccessRight.None; switch (entity.Rights) { case "GA": case "GXGW": case "GWGX": { rights = ApplicationAccessRight.Configure; break; } case "GX": { rights = ApplicationAccessRight.Run; break; } } if (rights == ApplicationAccessRight.None) { continue; } string accountName = ApplicationAccessRule.SidToAccountName(entity.AccountSid); if (String.IsNullOrEmpty(accountName)) { continue; } HttpAccessRule rule = new HttpAccessRule(); rule.UrlPrefix = url; rule.Right = rights; rule.IdentityName = accountName; accessRules.Add(rule); } }
/// <summary> /// Enables the menu items based on the current selection. /// </summary> protected override void EnableMenuItems(ListViewItem clickedItem) { base.EnableMenuItems(clickedItem); NewMI.Enabled = true; FileSystemAccessRule fileSystemRule = SelectedTag as FileSystemAccessRule; ApplicationAccessRule applicationRule = SelectedTag as ApplicationAccessRule; if (fileSystemRule != null || applicationRule != null) { EditMI.Enabled = true; DeleteMI.Enabled = true; } }
private void DeleteMI_Click(object sender, EventArgs e) { try { FileSystemAccessRule fileSystemRule = SelectedTag as FileSystemAccessRule; ApplicationAccessRule applicationRule = SelectedTag as ApplicationAccessRule; if (fileSystemRule == null && applicationRule == null) { return; } ItemsLV.SelectedItems[0].Remove(); } catch (Exception exception) { GuiUtils.HandleException(this.Text, System.Reflection.MethodBase.GetCurrentMethod(), exception); } }
/// <summary> /// Sets the application access rules for the specified URL (replaces the hostname with a wildcard). /// </summary> public static void SetAccessRules(Uri url, IList <ApplicationAccessRule> accessRules, bool replaceExisting) { StringBuilder wildcard = new StringBuilder(); wildcard.Append(url.Scheme); wildcard.Append("://+:"); wildcard.Append(url.Port); wildcard.Append(url.PathAndQuery); List <HttpAccessRule> httpRules = new List <HttpAccessRule>(); foreach (ApplicationAccessRule accessRule in accessRules) { // urls do not support deny rules. if (accessRule.RuleType == AccessControlType.Deny) { continue; } string identityName = accessRule.IdentityName; if (accessRule.IdentityName.StartsWith("S-")) { identityName = ApplicationAccessRule.SidToAccountName(accessRule.IdentityName); if (identityName == null) { Utils.Trace("Could not translate SID: {0}", accessRule.IdentityName); continue; } } HttpAccessRule httpRule = new HttpAccessRule(); httpRule.Right = accessRule.Right; httpRule.IdentityName = identityName; httpRules.Add(httpRule); } SetAccessRules(wildcard.ToString(), httpRules, replaceExisting); }
private void NewMI_Click(object sender, EventArgs e) { try { ApplicationAccessRule accessRule = new ApplicationAccessRule(); accessRule.RuleType = AccessControlType.Allow; accessRule.Right = ApplicationAccessRight.Run; if (!new AccessRuleDlg().ShowDialog(accessRule)) { return; } AddItem(accessRule); AdjustColumns(); } catch (Exception exception) { GuiUtils.HandleException(this.Text, System.Reflection.MethodBase.GetCurrentMethod(), exception); } }
/// <summary> /// Extracts the access rules from the SDDL string. /// </summary> private static string FormatSddl(IList <HttpAccessRule> accessRules) { StringBuilder builder = new StringBuilder(); builder.Append("D:"); for (int ii = 0; ii < accessRules.Count; ii++) { builder.Append("("); // start of ACE builder.Append("A;"); // access type builder.Append(";"); // flags switch (accessRules[ii].Right) { case ApplicationAccessRight.Configure: { builder.Append("GXGW;"); // rights break; } case ApplicationAccessRight.Run: case ApplicationAccessRight.Update: { builder.Append("GX;"); // rights break; } } builder.Append(";"); // object guid builder.Append(";"); // inherited object guid string sid = ApplicationAccessRule.AccountNameToSid(accessRules[ii].IdentityName); builder.Append(sid); builder.Append(')'); // end of ace. } return(builder.ToString()); }
/// <summary> /// Updates the access permissions for the certificate store. /// </summary> private static void SetCertificatePermissions( Opc.Ua.Security.SecuredApplication application, CertificateIdentifier id, IList <ApplicationAccessRule> accessRules, bool replaceExisting) { if (id == null || accessRules == null || accessRules.Count == 0) { return; } try { using (ICertificateStore store = id.OpenStore()) { if (store.SupportsCertificateAccessControl) { store.SetAccessRules(id.Thumbprint, accessRules, replaceExisting); } } } catch (Exception e) { Utils.Trace("Could not set permissions for certificate store: {0}. Error={1}", id, e.Message); for (int jj = 0; jj < accessRules.Count; jj++) { ApplicationAccessRule rule = accessRules[jj]; Utils.Trace( (int)Utils.TraceMasks.Error, "IdentityName={0}, Right={1}, RuleType={2}", rule.IdentityName, rule.Right, rule.RuleType); } } }
/// <summary> /// Returns the rules in the control. /// </summary> public IList <ApplicationAccessRule> GetAccessRules() { if (ItemsLV.Items.Count == 1) { if (ItemsLV.Items[0].Text == Instructions) { return(new ApplicationAccessRule[0]); } } List <ApplicationAccessRule> rules = new List <ApplicationAccessRule>(); for (int ii = 0; ii < ItemsLV.Items.Count; ii++) { ApplicationAccessRule applicationRule = ItemsLV.Items[ii].Tag as ApplicationAccessRule; if (applicationRule != null) { rules.Add(applicationRule); continue; } FileSystemAccessRule fileSystemRule = ItemsLV.Items[ii].Tag as FileSystemAccessRule; if (fileSystemRule != null) { applicationRule = new ApplicationAccessRule(); applicationRule.RuleType = ApplicationAccessRule.Convert(fileSystemRule.AccessControlType); applicationRule.Right = GetEffectiveRight(fileSystemRule); applicationRule.IdentityReference = fileSystemRule.IdentityReference; rules.Add(applicationRule); continue; } } return(rules.ToArray()); }
/// <summary> /// Gets the access rules to use for the application. /// </summary> private List<ApplicationAccessRule> GetAccessRules() { List<ApplicationAccessRule> rules = new List<ApplicationAccessRule>(); // check for rules specified in the installer configuration. bool hasAdmin = false; if (InstallConfig.AccessRules != null) { for (int ii = 0; ii < InstallConfig.AccessRules.Count; ii++) { ApplicationAccessRule rule = InstallConfig.AccessRules[ii]; if (rule.Right == ApplicationAccessRight.Configure && rule.RuleType == AccessControlType.Allow) { hasAdmin = true; break; } } rules = InstallConfig.AccessRules; } // provide some default rules. if (rules.Count == 0) { // give user run access. ApplicationAccessRule rule = new ApplicationAccessRule(); rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Run; rule.IdentityName = WellKnownSids.Users; rules.Add(rule); // ensure service can access. if (InstallConfig.InstallAsService) { rule = new ApplicationAccessRule(); rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Run; rule.IdentityName = WellKnownSids.NetworkService; rules.Add(rule); rule = new ApplicationAccessRule(); rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Run; rule.IdentityName = WellKnownSids.LocalService; rules.Add(rule); } } // ensure someone can change the configuration later. if (!hasAdmin) { ApplicationAccessRule rule = new ApplicationAccessRule(); rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Configure; rule.IdentityName = WellKnownSids.Administrators; rules.Add(rule); } return rules; }
/// <summary> /// Installs a UA application. /// </summary> public static void InstallApplication( InstalledApplication application, bool autostart, bool configureFirewall) { // validate the executable file. string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false); // get the default application name from the executable file. FileInfo executableFileInfo = new FileInfo(executableFile); string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length-4); // choose a default configuration file. if (String.IsNullOrEmpty(application.ConfigurationFile)) { application.ConfigurationFile = Utils.Format( "{0}\\{1}.Config.xml", executableFileInfo.DirectoryName, applicationName); } // validate the configuration file. string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false); // create a new file if one does not exist. bool useExisting = true; if (configurationFile == null) { configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, true, true); useExisting = false; } // create the default configuration file. if (useExisting) { try { Opc.Ua.Security.SecuredApplication existingSettings = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile); // copy current settings application.ApplicationType = existingSettings.ApplicationType; application.BaseAddresses = existingSettings.BaseAddresses; application.ApplicationCertificate = existingSettings.ApplicationCertificate; application.ApplicationName = existingSettings.ApplicationName; application.ProductName = existingSettings.ProductName; application.RejectedCertificatesStore = existingSettings.RejectedCertificatesStore; application.TrustedCertificateStore = existingSettings.TrustedCertificateStore; application.TrustedCertificates = existingSettings.TrustedCertificates; application.IssuerCertificateStore = existingSettings.IssuerCertificateStore; application.IssuerCertificates = application.IssuerCertificates; application.UseDefaultCertificateStores = false; } catch (Exception e) { useExisting = false; Utils.Trace("WARNING. Existing configuration file could not be loaded: {0}.\r\nReplacing with default: {1}", e.Message, configurationFile); File.Copy(configurationFile, configurationFile + ".bak", true); } } // create the configuration file from the default. if (!useExisting) { try { string installationFile = Utils.Format( "{0}\\Install\\{1}.Config.xml", executableFileInfo.Directory.Parent.FullName, applicationName); if (!File.Exists(installationFile)) { Utils.Trace("Could not find default configuation at: {0}", installationFile); } File.Copy(installationFile, configurationFile, true); Utils.Trace("File.Copy({0}, {1})", installationFile, configurationFile); } catch (Exception e) { Utils.Trace("Could not copy default configuation to: {0}. Error={1}.", configurationFile, e.Message); } } // create a default application name. if (String.IsNullOrEmpty(application.ApplicationName)) { application.ApplicationName = applicationName; } // create a default product name. if (String.IsNullOrEmpty(application.ProductName)) { application.ProductName = application.ApplicationName; } // create a default uri. if (String.IsNullOrEmpty(application.ApplicationUri)) { application.ApplicationUri = Utils.Format("http://localhost/{0}/{1}", applicationName, Guid.NewGuid()); } // make the uri specify the local machine. application.ApplicationUri = Utils.ReplaceLocalhost(application.ApplicationUri); // set a default application store. if (application.ApplicationCertificate == null) { application.ApplicationCertificate = new Opc.Ua.Security.CertificateIdentifier(); application.ApplicationCertificate.StoreType = Utils.DefaultStoreType; application.ApplicationCertificate.StorePath = Utils.DefaultStorePath; } if (application.UseDefaultCertificateStores) { if (application.IssuerCertificateStore == null) { application.IssuerCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.IssuerCertificateStore.StoreType = Utils.DefaultStoreType; application.IssuerCertificateStore.StorePath = Utils.DefaultStorePath; } if (application.TrustedCertificateStore == null) { application.TrustedCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.TrustedCertificateStore.StoreType = Utils.DefaultStoreType; application.TrustedCertificateStore.StorePath = Utils.DefaultStorePath; } try { Utils.GetAbsoluteDirectoryPath(application.TrustedCertificateStore.StorePath, true, true, true); } catch (Exception e) { Utils.Trace("Could not access the machine directory: {0} '{1}'", application.RejectedCertificatesStore.StorePath, e); } if (application.RejectedCertificatesStore == null) { application.RejectedCertificatesStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.RejectedCertificatesStore.StoreType = CertificateStoreType.Directory; application.RejectedCertificatesStore.StorePath = "%CommonApplicationData%\\OPC Foundation\\CertificateStores\\RejectedCertificates"; StringBuilder buffer = new StringBuilder(); buffer.Append(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); buffer.Append("\\OPC Foundation"); buffer.Append("\\RejectedCertificates"); string folderPath = buffer.ToString(); if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } } } // check for valid certificate (discard invalid certificates). CertificateIdentifier applicationCertificate = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(application.ApplicationCertificate); X509Certificate2 certificate = applicationCertificate.Find(true); if (certificate == null) { certificate = applicationCertificate.Find(false); if (certificate != null) { Utils.Trace( "Found existing certificate but it does not have a private key: Store={0}, Certificate={1}", application.ApplicationCertificate.StorePath, application.ApplicationCertificate); } else { Utils.Trace( "Existing certificate could not be found: Store={0}, Certificate={1}", application.ApplicationCertificate.StorePath, application.ApplicationCertificate); } } // check if no certificate exists. if (certificate == null) { certificate = CreateCertificateForApplication(application); } // ensure the application certificate is in the trusted peers store. try { CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.TrustedCertificateStore); using (ICertificateStore store = certificateStore.OpenStore()) { X509Certificate2 peerCertificate = store.FindByThumbprint(certificate.Thumbprint); if (peerCertificate == null) { store.Add(new X509Certificate2(certificate.GetRawCertData())); } } } catch (Exception e) { Utils.Trace( "Could not add certificate '{0}' to trusted peer store '{1}'. Error={2}", certificate.Subject, application.TrustedCertificateStore, e.Message); } // locally register the certficate OIDs. if (application.LocallyRegisterOIDs) { try { LocallyRegisterCertificateOIDs(certificate); } catch (Exception e) { Utils.Trace( "Could not register OIDs used for certificate '{0}'. Error={1}", certificate.Subject, e.Message); } } // update configuration file location. UpdateConfigurationLocation(executableFile, configurationFile); // update configuration file. new Opc.Ua.Security.SecurityConfigurationManager().WriteConfiguration(configurationFile, application); // configure firewall. if (configureFirewall && application.ConfigureFirewall) { if (application.BaseAddresses != null && application.BaseAddresses.Count > 0) { try { SetFirewallAccess(application, executableFile); } catch (Exception e) { Utils.Trace("Could not set firewall access for executable: {0}. Error={1}", executableFile, e.Message); } } } ApplicationAccessRuleCollection accessRules = application.AccessRules; bool noRulesDefined = application.AccessRules == null || application.AccessRules.Count == 0; // add the default access rules. if (noRulesDefined) { ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Administrators; rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Configure; accessRules.Add(rule); rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Users; rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Update; accessRules.Add(rule); } // ensure the service account has priviledges. if (application.InstallAsService) { // check if a specific account is assigned. AccountInfo accountInfo = null; if (!String.IsNullOrEmpty(application.ServiceUserName)) { accountInfo = AccountInfo.Create(application.ServiceUserName); } // choose a built-in service account. if (accountInfo == null) { accountInfo = AccountInfo.Create(WellKnownSids.NetworkService); if (accountInfo == null) { accountInfo = AccountInfo.Create(WellKnownSids.LocalSystem); } } ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = accountInfo.ToString(); rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Run; accessRules.Add(rule); } // set the permissions for the HTTP endpoints used by the application. if (configureFirewall && application.BaseAddresses != null && application.BaseAddresses.Count > 0) { for (int ii = 0; ii < application.BaseAddresses.Count; ii++) { Uri url = Utils.ParseUri(application.BaseAddresses[ii]); if (url != null) { if (url.Scheme == Uri.UriSchemeHttp || url.Scheme == Uri.UriSchemeHttps) { try { HttpAccessRule.SetAccessRules(url, accessRules, true); Utils.Trace("Added HTTP access rules for URL: {0}", url); } catch (Exception e) { Utils.Trace("Could not set HTTP access rules for URL: {0}. Error={1}", url, e.Message); for (int jj = 0; jj < accessRules.Count; jj++) { ApplicationAccessRule rule = accessRules[jj]; Utils.Trace( (int)Utils.TraceMasks.Error, "IdentityName={0}, Right={1}, RuleType={2}", rule.IdentityName, rule.Right, rule.RuleType); } } } } } } // set permissions on the local certificate store. SetCertificatePermissions( application, applicationCertificate, accessRules, false); // set permissions on the local certificate store. if (application.RejectedCertificatesStore != null) { // need to grant full control to certificates in the RejectedCertificatesStore. foreach (ApplicationAccessRule rule in accessRules) { if (rule.RuleType == AccessControlType.Allow) { rule.Right = ApplicationAccessRight.Configure; } } CertificateStoreIdentifier rejectedCertificates = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.RejectedCertificatesStore); using (ICertificateStore store = rejectedCertificates.OpenStore()) { if (store.SupportsAccessControl) { store.SetAccessRules(accessRules, false); } } } // install as a service. if (application.InstallAsService) { ServiceInstaller.UnInstallService(application.ApplicationName); StartMode startMode = application.ServiceStartMode; if (!autostart) { startMode = StartMode.Manual; } bool start = true; bool result = ServiceInstaller.InstallService( executableFileInfo.FullName, application.ApplicationName, application.ApplicationName, application.ServiceDescription, startMode, application.ServiceUserName, application.ServicePassword, ref start); if (!result) { throw new ApplicationException("Could not install service."); } } }
/// <summary> /// Installs a UA application. /// </summary> public static async Task InstallApplication( InstalledApplication application, bool autostart, bool configureFirewall) { // validate the executable file. string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false); // get the default application name from the executable file. FileInfo executableFileInfo = new FileInfo(executableFile); string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length - 4); // choose a default configuration file. if (String.IsNullOrEmpty(application.ConfigurationFile)) { application.ConfigurationFile = Utils.Format( "{0}\\{1}.Config.xml", executableFileInfo.DirectoryName, applicationName); } // validate the configuration file. string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false); // create a new file if one does not exist. bool useExisting = true; if (configurationFile == null) { configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, true, true); useExisting = false; } // create the default configuration file. if (useExisting) { try { Opc.Ua.Security.SecuredApplication existingSettings = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile); // copy current settings application.ApplicationType = existingSettings.ApplicationType; application.BaseAddresses = existingSettings.BaseAddresses; application.ApplicationCertificate = existingSettings.ApplicationCertificate; application.ApplicationName = existingSettings.ApplicationName; application.ProductName = existingSettings.ProductName; application.RejectedCertificatesStore = existingSettings.RejectedCertificatesStore; application.TrustedCertificateStore = existingSettings.TrustedCertificateStore; application.TrustedCertificates = existingSettings.TrustedCertificates; application.IssuerCertificateStore = existingSettings.IssuerCertificateStore; application.IssuerCertificates = application.IssuerCertificates; application.UseDefaultCertificateStores = false; } catch (Exception e) { useExisting = false; Utils.Trace("WARNING. Existing configuration file could not be loaded: {0}.\r\nReplacing with default: {1}", e.Message, configurationFile); File.Copy(configurationFile, configurationFile + ".bak", true); } } // create the configuration file from the default. if (!useExisting) { try { string installationFile = Utils.Format( "{0}\\Install\\{1}.Config.xml", executableFileInfo.Directory.Parent.FullName, applicationName); if (!File.Exists(installationFile)) { Utils.Trace("Could not find default configuation at: {0}", installationFile); } File.Copy(installationFile, configurationFile, true); Utils.Trace("File.Copy({0}, {1})", installationFile, configurationFile); } catch (Exception e) { Utils.Trace("Could not copy default configuation to: {0}. Error={1}.", configurationFile, e.Message); } } // create a default application name. if (String.IsNullOrEmpty(application.ApplicationName)) { application.ApplicationName = applicationName; } // create a default product name. if (String.IsNullOrEmpty(application.ProductName)) { application.ProductName = application.ApplicationName; } // create a default uri. if (String.IsNullOrEmpty(application.ApplicationUri)) { application.ApplicationUri = Utils.Format("http://localhost/{0}/{1}", applicationName, Guid.NewGuid()); } // make the uri specify the local machine. application.ApplicationUri = Utils.ReplaceLocalhost(application.ApplicationUri); // set a default application store. if (application.ApplicationCertificate == null) { application.ApplicationCertificate = new Opc.Ua.Security.CertificateIdentifier(); application.ApplicationCertificate.StoreType = Utils.DefaultStoreType; application.ApplicationCertificate.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault"; } if (application.UseDefaultCertificateStores) { if (application.IssuerCertificateStore == null) { application.IssuerCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.IssuerCertificateStore.StoreType = Utils.DefaultStoreType; application.IssuerCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault"; } if (application.TrustedCertificateStore == null) { application.TrustedCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.TrustedCertificateStore.StoreType = Utils.DefaultStoreType; application.TrustedCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault"; } try { Utils.GetAbsoluteDirectoryPath(application.TrustedCertificateStore.StorePath, true, true, true); } catch (Exception e) { Utils.Trace("Could not access the machine directory: {0} '{1}'", application.RejectedCertificatesStore.StorePath, e); } if (application.RejectedCertificatesStore == null) { application.RejectedCertificatesStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.RejectedCertificatesStore.StoreType = CertificateStoreType.Directory; application.RejectedCertificatesStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\RejectedCertificates"; StringBuilder buffer = new StringBuilder(); buffer.Append(ApplicationData.Current.LocalFolder.Path); buffer.Append("\\OPC Foundation"); buffer.Append("\\RejectedCertificates"); string folderPath = buffer.ToString(); if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } } } // check for valid certificate (discard invalid certificates). CertificateIdentifier applicationCertificate = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(application.ApplicationCertificate); X509Certificate2 certificate = await applicationCertificate.Find(true); if (certificate == null) { certificate = await applicationCertificate.Find(false); if (certificate != null) { Utils.Trace( "Found existing certificate but it does not have a private key: Store={0}, Certificate={1}", application.ApplicationCertificate.StorePath, application.ApplicationCertificate); } else { Utils.Trace( "Existing certificate could not be found: Store={0}, Certificate={1}", application.ApplicationCertificate.StorePath, application.ApplicationCertificate); } } // check if no certificate exists. if (certificate == null) { certificate = await CreateCertificateForApplication(application); } // ensure the application certificate is in the trusted peers store. try { CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.TrustedCertificateStore); using (ICertificateStore store = certificateStore.OpenStore()) { X509Certificate2Collection peerCertificates = await store.FindByThumbprint(certificate.Thumbprint); if (peerCertificates.Count == 0) { await store.Add(new X509Certificate2(certificate.RawData)); } } } catch (Exception e) { Utils.Trace( "Could not add certificate '{0}' to trusted peer store '{1}'. Error={2}", certificate.Subject, application.TrustedCertificateStore, e.Message); } // update configuration file location. UpdateConfigurationLocation(executableFile, configurationFile); // update configuration file. new Opc.Ua.Security.SecurityConfigurationManager().WriteConfiguration(configurationFile, application); ApplicationAccessRuleCollection accessRules = application.AccessRules; bool noRulesDefined = application.AccessRules == null || application.AccessRules.Count == 0; // add the default access rules. if (noRulesDefined) { ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Administrators; rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Configure; accessRules.Add(rule); rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Users; rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Update; accessRules.Add(rule); } // ensure the service account has priviledges. if (application.InstallAsService) { // check if a specific account is assigned. AccountInfo accountInfo = null; if (!String.IsNullOrEmpty(application.ServiceUserName)) { accountInfo = AccountInfo.Create(application.ServiceUserName); } // choose a built-in service account. if (accountInfo == null) { accountInfo = AccountInfo.Create(WellKnownSids.NetworkService); if (accountInfo == null) { accountInfo = AccountInfo.Create(WellKnownSids.LocalSystem); } } ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = accountInfo.ToString(); rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Run; accessRules.Add(rule); } // set the permissions for the HTTP endpoints used by the application. if (configureFirewall && application.BaseAddresses != null && application.BaseAddresses.Count > 0) { for (int ii = 0; ii < application.BaseAddresses.Count; ii++) { Uri url = Utils.ParseUri(application.BaseAddresses[ii]); if (url != null) { try { HttpAccessRule.SetAccessRules(url, accessRules, true); Utils.Trace("Added HTTP access rules for URL: {0}", url); } catch (Exception e) { Utils.Trace("Could not set HTTP access rules for URL: {0}. Error={1}", url, e.Message); for (int jj = 0; jj < accessRules.Count; jj++) { ApplicationAccessRule rule = accessRules[jj]; Utils.Trace( (int)Utils.TraceMasks.Error, "IdentityName={0}, Right={1}, RuleType={2}", rule.IdentityName, rule.Right, rule.RuleType); } } } } } // set permissions on the local certificate store. SetCertificatePermissions( application, applicationCertificate, accessRules, false); // set permissions on the local certificate store. if (application.RejectedCertificatesStore != null) { // need to grant full control to certificates in the RejectedCertificatesStore. foreach (ApplicationAccessRule rule in accessRules) { if (rule.RuleType == AccessControlType.Allow) { rule.Right = ApplicationAccessRight.Configure; } } CertificateStoreIdentifier rejectedCertificates = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.RejectedCertificatesStore); using (ICertificateStore store = rejectedCertificates.OpenStore()) { if (store.SupportsAccessControl) { store.SetAccessRules(accessRules, false); } } } }
/// <summary> /// Returns the rules in the control. /// </summary> public IList<ApplicationAccessRule> GetAccessRules() { if (ItemsLV.Items.Count == 1) { if (ItemsLV.Items[0].Text == Instructions) { return new ApplicationAccessRule[0]; } } List<ApplicationAccessRule> rules = new List<ApplicationAccessRule>(); for (int ii = 0; ii < ItemsLV.Items.Count; ii++) { ApplicationAccessRule applicationRule = ItemsLV.Items[ii].Tag as ApplicationAccessRule; if (applicationRule != null) { rules.Add(applicationRule); continue; } FileSystemAccessRule fileSystemRule = ItemsLV.Items[ii].Tag as FileSystemAccessRule; if (fileSystemRule != null) { applicationRule = new ApplicationAccessRule(); applicationRule.RuleType = ApplicationAccessRule.Convert(fileSystemRule.AccessControlType); applicationRule.Right = GetEffectiveRight(fileSystemRule); applicationRule.IdentityReference = fileSystemRule.IdentityReference; rules.Add(applicationRule); continue; } } return rules.ToArray(); }
/// <summary> /// Installs a UA application. /// </summary> public static async Task InstallApplication( InstalledApplication application, bool autostart, bool configureFirewall) { // validate the executable file. string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false); // get the default application name from the executable file. FileInfo executableFileInfo = new FileInfo(executableFile); string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length-4); // choose a default configuration file. if (String.IsNullOrEmpty(application.ConfigurationFile)) { application.ConfigurationFile = Utils.Format( "{0}\\{1}.Config.xml", executableFileInfo.DirectoryName, applicationName); } // validate the configuration file. string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false); // create a new file if one does not exist. bool useExisting = true; if (configurationFile == null) { configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, true, true); useExisting = false; } // create the default configuration file. if (useExisting) { try { Opc.Ua.Security.SecuredApplication existingSettings = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile); // copy current settings application.ApplicationType = existingSettings.ApplicationType; application.BaseAddresses = existingSettings.BaseAddresses; application.ApplicationCertificate = existingSettings.ApplicationCertificate; application.ApplicationName = existingSettings.ApplicationName; application.ProductName = existingSettings.ProductName; application.RejectedCertificatesStore = existingSettings.RejectedCertificatesStore; application.TrustedCertificateStore = existingSettings.TrustedCertificateStore; application.TrustedCertificates = existingSettings.TrustedCertificates; application.IssuerCertificateStore = existingSettings.IssuerCertificateStore; application.IssuerCertificates = application.IssuerCertificates; application.UseDefaultCertificateStores = false; } catch (Exception e) { useExisting = false; Utils.Trace("WARNING. Existing configuration file could not be loaded: {0}.\r\nReplacing with default: {1}", e.Message, configurationFile); File.Copy(configurationFile, configurationFile + ".bak", true); } } // create the configuration file from the default. if (!useExisting) { try { string installationFile = Utils.Format( "{0}\\Install\\{1}.Config.xml", executableFileInfo.Directory.Parent.FullName, applicationName); if (!File.Exists(installationFile)) { Utils.Trace("Could not find default configuation at: {0}", installationFile); } File.Copy(installationFile, configurationFile, true); Utils.Trace("File.Copy({0}, {1})", installationFile, configurationFile); } catch (Exception e) { Utils.Trace("Could not copy default configuation to: {0}. Error={1}.", configurationFile, e.Message); } } // create a default application name. if (String.IsNullOrEmpty(application.ApplicationName)) { application.ApplicationName = applicationName; } // create a default product name. if (String.IsNullOrEmpty(application.ProductName)) { application.ProductName = application.ApplicationName; } // create a default uri. if (String.IsNullOrEmpty(application.ApplicationUri)) { application.ApplicationUri = Utils.Format("http://localhost/{0}/{1}", applicationName, Guid.NewGuid()); } // make the uri specify the local machine. application.ApplicationUri = Utils.ReplaceLocalhost(application.ApplicationUri); // set a default application store. if (application.ApplicationCertificate == null) { application.ApplicationCertificate = new Opc.Ua.Security.CertificateIdentifier(); application.ApplicationCertificate.StoreType = Utils.DefaultStoreType; application.ApplicationCertificate.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault"; } if (application.UseDefaultCertificateStores) { if (application.IssuerCertificateStore == null) { application.IssuerCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.IssuerCertificateStore.StoreType = Utils.DefaultStoreType; application.IssuerCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault"; } if (application.TrustedCertificateStore == null) { application.TrustedCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.TrustedCertificateStore.StoreType = Utils.DefaultStoreType; application.TrustedCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault"; } try { Utils.GetAbsoluteDirectoryPath(application.TrustedCertificateStore.StorePath, true, true, true); } catch (Exception e) { Utils.Trace("Could not access the machine directory: {0} '{1}'", application.RejectedCertificatesStore.StorePath, e); } if (application.RejectedCertificatesStore == null) { application.RejectedCertificatesStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.RejectedCertificatesStore.StoreType = CertificateStoreType.Directory; application.RejectedCertificatesStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\RejectedCertificates"; StringBuilder buffer = new StringBuilder(); buffer.Append(ApplicationData.Current.LocalFolder.Path); buffer.Append("\\OPC Foundation"); buffer.Append("\\RejectedCertificates"); string folderPath = buffer.ToString(); if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } } } // check for valid certificate (discard invalid certificates). CertificateIdentifier applicationCertificate = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(application.ApplicationCertificate); X509Certificate2 certificate = await applicationCertificate.Find(true); if (certificate == null) { certificate = await applicationCertificate.Find(false); if (certificate != null) { Utils.Trace( "Found existing certificate but it does not have a private key: Store={0}, Certificate={1}", application.ApplicationCertificate.StorePath, application.ApplicationCertificate); } else { Utils.Trace( "Existing certificate could not be found: Store={0}, Certificate={1}", application.ApplicationCertificate.StorePath, application.ApplicationCertificate); } } // check if no certificate exists. if (certificate == null) { certificate = await CreateCertificateForApplication(application); } // ensure the application certificate is in the trusted peers store. try { CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.TrustedCertificateStore); using (ICertificateStore store = certificateStore.OpenStore()) { X509Certificate2Collection peerCertificates = await store.FindByThumbprint(certificate.Thumbprint); if (peerCertificates.Count == 0) { await store.Add(new X509Certificate2(certificate.RawData)); } } } catch (Exception e) { Utils.Trace( "Could not add certificate '{0}' to trusted peer store '{1}'. Error={2}", certificate.Subject, application.TrustedCertificateStore, e.Message); } // update configuration file location. UpdateConfigurationLocation(executableFile, configurationFile); // update configuration file. new Opc.Ua.Security.SecurityConfigurationManager().WriteConfiguration(configurationFile, application); ApplicationAccessRuleCollection accessRules = application.AccessRules; bool noRulesDefined = application.AccessRules == null || application.AccessRules.Count == 0; // add the default access rules. if (noRulesDefined) { ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Administrators; rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Configure; accessRules.Add(rule); rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Users; rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Update; accessRules.Add(rule); } // ensure the service account has priviledges. if (application.InstallAsService) { // check if a specific account is assigned. AccountInfo accountInfo = null; if (!String.IsNullOrEmpty(application.ServiceUserName)) { accountInfo = AccountInfo.Create(application.ServiceUserName); } // choose a built-in service account. if (accountInfo == null) { accountInfo = AccountInfo.Create(WellKnownSids.NetworkService); if (accountInfo == null) { accountInfo = AccountInfo.Create(WellKnownSids.LocalSystem); } } ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = accountInfo.ToString(); rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Run; accessRules.Add(rule); } // set permissions on the local certificate store. SetCertificatePermissions( application, applicationCertificate, accessRules, false); // set permissions on the local certificate store. if (application.RejectedCertificatesStore != null) { // need to grant full control to certificates in the RejectedCertificatesStore. foreach (ApplicationAccessRule rule in accessRules) { if (rule.RuleType == AccessControlType.Allow) { rule.Right = ApplicationAccessRight.Configure; } } CertificateStoreIdentifier rejectedCertificates = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.RejectedCertificatesStore); using (ICertificateStore store = rejectedCertificates.OpenStore()) { if (store.SupportsAccessControl) { store.SetAccessRules(accessRules, false); } } } }