1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/lishilei0523-h-opc

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
ApplicationInstance.cs 77 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Lee Отправлено 6 лет назад b2a9c58
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057
/* ========================================================================
* Copyright (c) 2005-2013 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security.Cryptography.X509Certificates;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
namespace Opc.Ua.Configuration
{
/// <summary>
/// A class that install, configures and runs a UA application.
/// </summary>
public class ApplicationInstance
{
#region Ctors
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationInstance"/> class.
/// </summary>
public ApplicationInstance()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationInstance"/> class.
/// </summary>
/// <param name="applicationConfiguration">The application configuration.</param>
public ApplicationInstance(ApplicationConfiguration applicationConfiguration)
{
m_applicationConfiguration = applicationConfiguration;
}
#endregion
#region Public Properties
/// <summary>
/// Gets or sets the name of the application.
/// </summary>
/// <value>The name of the application.</value>
public string ApplicationName
{
get { return m_applicationName; }
set { m_applicationName = value; }
}
/// <summary>
/// Gets or sets the type of the application.
/// </summary>
/// <value>The type of the application.</value>
public ApplicationType ApplicationType
{
get { return m_applicationType; }
set { m_applicationType = value; }
}
/// <summary>
/// Gets or sets the name of the config section containing the path to the application configuration file.
/// </summary>
/// <value>The name of the config section.</value>
public string ConfigSectionName
{
get { return m_configSectionName; }
set { m_configSectionName = value; }
}
/// <summary>
/// Gets or sets the type of configuration file.
/// </summary>
/// <value>The type of configuration file.</value>
public Type ConfigurationType
{
get { return m_configurationType; }
set { m_configurationType = value; }
}
/// <summary>
/// Gets or sets the installation configuration.
/// </summary>
/// <value>The installation configuration.</value>
public InstalledApplication InstallConfig
{
get { return m_installConfig; }
set { m_installConfig = value; }
}
/// <summary>
/// Gets the server.
/// </summary>
/// <value>The server.</value>
public ServerBase Server
{
get { return m_server; }
}
/// <summary>
/// Gets the application configuration used when the Start() method was called.
/// </summary>
/// <value>The application configuration.</value>
public ApplicationConfiguration ApplicationConfiguration
{
get { return m_applicationConfiguration; }
set { m_applicationConfiguration = value; }
}
/// <summary>
/// Gets or sets a flag that indicates whether the application will be set up for management with the GDS agent.
/// </summary>
/// <value>If true the application will not be visible to the GDS local agent after installation.</value>
public bool NoGdsAgentAdmin { get; set; }
#endregion
#region InstallConfig Handling
/// <summary>
/// Loads the installation configuration from a file.
/// </summary>
public InstalledApplication LoadInstallConfigFromFile(string filePath)
{
if (filePath == null) throw new ArgumentNullException("filePath");
Stream istrm = null;
try
{
istrm = File.Open(filePath, FileMode.Open, FileAccess.Read);
}
catch (Exception e)
{
throw ServiceResultException.Create(StatusCodes.BadDecodingError, e, "Could not open file: {0}", filePath);
}
return LoadInstallConfigFromStream(istrm);
}
/// <summary>
/// Loads the installation configuration from an embedded resource.
/// </summary>
public InstalledApplication LoadInstallConfigFromResource(string resourcePath, Assembly assembly)
{
if (resourcePath == null) throw new ArgumentNullException("resourcePath");
if (assembly == null)
{
assembly = Assembly.GetCallingAssembly();
}
Stream istrm = assembly.GetManifestResourceStream(resourcePath);
if (istrm == null)
{
throw ServiceResultException.Create(StatusCodes.BadDecodingError, "Could not find resource file: {0}", resourcePath);
}
return LoadInstallConfigFromStream(istrm);
}
/// <summary>
/// Loads the installation configuration from a stream.
/// </summary>
public InstalledApplication LoadInstallConfigFromStream(Stream istrm)
{
try
{
using (XmlTextReader reader = new XmlTextReader(istrm))
{
DataContractSerializer serializer = new DataContractSerializer(typeof(InstalledApplication));
return (InstalledApplication)serializer.ReadObject(reader, false);
}
}
catch (Exception e)
{
throw ServiceResultException.Create(StatusCodes.BadDecodingError, e, "Could not parse install configuration.");
}
}
/// <summary>
/// Loads the installation configuration.
/// </summary>
/// <param name="configFile">The config file (may be null).</param>
public virtual void LoadInstallConfig(string configFile)
{
// load configuration from command line.
if (!String.IsNullOrEmpty(configFile))
{
InstallConfig = LoadInstallConfigFromFile(configFile);
}
// load it from a resource if not already loaded.
else if (InstallConfig == null)
{
foreach (string resourcePath in Assembly.GetEntryAssembly().GetManifestResourceNames())
{
if (resourcePath.EndsWith("InstallConfig.xml"))
{
InstallConfig = LoadInstallConfigFromResource(resourcePath, Assembly.GetEntryAssembly());
break;
}
}
if (InstallConfig == null)
{
throw new ServiceResultException(StatusCodes.BadConfigurationError, "Could not load default installation config file.");
}
}
// override the application name.
if (String.IsNullOrEmpty(InstallConfig.ApplicationName))
{
InstallConfig.ApplicationName = ApplicationName;
}
else
{
ApplicationName = InstallConfig.ApplicationName;
}
// update fixed fields in the installation config.
InstallConfig.ApplicationType = (Opc.Ua.Security.ApplicationType)(int)ApplicationType;
InstallConfig.ExecutableFile = Application.ExecutablePath;
if (InstallConfig.TraceConfiguration != null)
{
InstallConfig.TraceConfiguration.ApplySettings();
}
}
#endregion
#region Public Methods
/// <summary>
/// Processes the command line.
/// </summary>
/// <returns>
/// True if the arguments were processed; False otherwise.
/// </returns>
public bool ProcessCommandLine()
{
// NP Jan-20-2012: removing GDS reference, per new OPCF decree of no GDS.
NoGdsAgentAdmin = true;
return ProcessCommandLine(false);
}
/// <summary>
/// Processes the command line.
/// </summary>
/// <param name="ignoreUnknownArguments">if set to <c>true</c> unknown arguments are ignored.</param>
/// <returns>
/// True if the arguments were processed; False otherwise.
/// </returns>
public bool ProcessCommandLine(bool ignoreUnknownArguments)
{
TraceConfiguration config = new TraceConfiguration();
config.OutputFilePath = "%CommonApplicationData%\\OPC Foundation\\Logs\\Default.InstallLog.txt";
config.DeleteOnLoad = false;
config.TraceMasks = 1023;
config.ApplySettings();
string[] args = Environment.GetCommandLineArgs();
if (args.Length <= 1)
{
return false;
}
return ProcessCommandLine(ignoreUnknownArguments, args);
}
/// <summary>
/// Processes the command line.
/// </summary>
/// <returns>True if the arguments were processed; False otherwise.</returns>
public bool ProcessCommandLine(bool ignoreUnknownArguments, params string[] args)
{
if (args.Length <= 1)
{
return false;
}
// arguments can be standalone or name-value pairs seperated by a ':'.
Dictionary<string, string> argTable = new Dictionary<string, string>();
for (int ii = 1; ii < args.Length; ii++)
{
string arg = args[ii];
if (String.IsNullOrEmpty(arg))
{
continue;
}
int index = args[ii].IndexOf(':');
if (index != -1 && index > 0 && index < arg.Length - 1)
{
argTable[arg.Substring(0, index).ToLower()] = arg.Substring(index + 1);
}
else
{
argTable[arg.ToLower()] = String.Empty;
}
}
// validate arguments.
string error = ValidateArguments(ignoreUnknownArguments, argTable);
if (!String.IsNullOrEmpty(error))
{
throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, error);
}
// check for the silent switch.
bool silent = !Environment.UserInteractive;
if (argTable.ContainsKey("/silent"))
{
silent = true;
}
string configFile = null;
try
{
// get configuration file from command line.
if (argTable.TryGetValue("/configfile", out configFile))
{
configFile = Utils.GetAbsoluteFilePath(configFile, true, true, false);
}
// load the configuration.
LoadInstallConfig(configFile);
}
catch (Exception e)
{
StringBuilder buffer = new StringBuilder();
buffer.Append("Could not load the install configuration. ");
buffer.Append(configFile);
if (!silent)
{
throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, e, buffer.ToString());
}
Utils.Trace(e, buffer.ToString());
return true;
}
try
{
// install the application.
if (argTable.ContainsKey("/start"))
{
if (Opc.Ua.Configuration.ServiceInstaller.StartService(InstallConfig.ApplicationName))
{
Utils.Trace(Utils.TraceMasks.Information, "Service started '{0}'.", InstallConfig.ApplicationName);
}
return true;
}
// install the application.
if (argTable.ContainsKey("/install"))
{
Install(silent, argTable);
return true;
}
// uninstall the application.
if (argTable.ContainsKey("/uninstall"))
{
Uninstall(silent, argTable);
return true;
}
// handle any argument defined by the subclass.
return ProcessCommand(silent, argTable);
}
catch (Exception e)
{
StringBuilder buffer = new StringBuilder();
buffer.Append("Could not process the command line arguments provided. ");
if (args != null)
{
for (int ii = 1; ii < args.Length; ii++)
{
buffer.AppendFormat("{0} ", args[ii]);
}
}
if (!silent)
{
throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, e, buffer.ToString());
}
Utils.Trace(e, buffer.ToString());
return true;
}
}
/// <summary>
/// Starts the UA server as a Windows Service.
/// </summary>
/// <param name="server">The server.</param>
public void StartAsService(ServerBase server)
{
m_server = server;
ServiceBase.Run(new WindowsService(server, ConfigSectionName, ApplicationType, ConfigurationType));
}
/// <summary>
/// Starts the UA server.
/// </summary>
/// <param name="server">The server.</param>
public void Start(ServerBase server)
{
m_server = server;
if (m_applicationConfiguration == null)
{
LoadApplicationConfiguration(false);
}
if (m_applicationConfiguration.SecurityConfiguration != null && m_applicationConfiguration.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
m_applicationConfiguration.CertificateValidator.CertificateValidation += CertificateValidator_CertificateValidation;
}
server.Start(m_applicationConfiguration);
}
/// <summary>
/// Stops the UA server.
/// </summary>
public void Stop()
{
m_server.Stop();
}
#endregion
#region WindowsService Class
/// <summary>
/// Manages the interface between the UA server and the Windows SCM.
/// </summary>
protected class WindowsService : ServiceBase
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="WindowsService"/> class.
/// </summary>
/// <param name="server">The server.</param>
/// <param name="configSectionName">Name of the config section.</param>
/// <param name="applicationType">Type of the application.</param>
/// <param name="configurationType">Type of the configuration.</param>
public WindowsService(ServerBase server, string configSectionName, ApplicationType applicationType, Type configurationType)
{
m_server = server;
m_configSectionName = configSectionName;
m_applicationType = applicationType;
m_configurationType = configurationType;
EventLog.Source = "UA Application";
}
#endregion
#region Overridden Methods
/// <summary>
/// Starts the server in a background thread.
/// </summary>
protected override void OnStart(string[] args)
{
Thread thread = new Thread(OnBackgroundStart);
thread.Start(null);
}
/// <summary>
/// Stops the server so the service can shutdown.
/// </summary>
protected override void OnStop()
{
m_server.Stop();
}
#endregion
#region Private Methods
/// <summary>
/// Runs the service in a background thread.
/// </summary>
private void OnBackgroundStart(object state)
{
string filePath = null;
ApplicationConfiguration configuration = null;
try
{
filePath = ApplicationConfiguration.GetFilePathFromAppConfig(m_configSectionName);
configuration = ApplicationInstance.LoadAppConfig(false, filePath, m_applicationType, m_configurationType, true);
}
catch (Exception e)
{
ServiceResult error = ServiceResult.Create(e, StatusCodes.BadConfigurationError, "Could not load UA Service configuration file.\r\nPATH={0}", filePath);
this.EventLog.WriteEntry(error.ToLongString(), EventLogEntryType.Error);
}
try
{
if (configuration.SecurityConfiguration != null && configuration.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
configuration.CertificateValidator.CertificateValidation += CertificateValidator_CertificateValidation;
}
m_server.Start(configuration);
// this.EventLog.WriteEntry("SERVICE STARTED! " + this.m_configSectionName, EventLogEntryType.Information);
}
catch (Exception e)
{
ServiceResult error = ServiceResult.Create(e, StatusCodes.BadConfigurationError, "Could not start UA Service.");
this.EventLog.WriteEntry(error.ToLongString(), EventLogEntryType.Error);
Utils.Trace((int)Utils.TraceMasks.Error, error.ToLongString());
}
}
#endregion
#region Private Fields
private ServerBase m_server;
private string m_configSectionName;
private ApplicationType m_applicationType;
private Type m_configurationType;
#endregion
}
#endregion
#region ArgumentDescription Class
/// <summary>
/// Stores the description of an argument.
/// </summary>
protected class ArgumentDescription
{
/// <summary>
/// The argument name.
/// </summary>
public string Name;
/// <summary>
/// The argument description.
/// </summary>
public string Description;
/// <summary>
/// Whether the argument requires a value.
/// </summary>
public bool ValueRequired;
/// <summary>
/// Whether the argument allows a value.
/// </summary>
public bool ValueAllowed;
/// <summary>
/// Initializes a new instance of the <see cref="ArgumentDescription"/> class.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="valueRequired">if set to <c>true</c> a value is required.</param>
/// <param name="valueAllowed">if set to <c>true</c> a value is allowed.</param>
/// <param name="description">The description.</param>
public ArgumentDescription(
string name,
bool valueRequired,
bool valueAllowed,
string description)
{
Name = name;
ValueRequired = valueRequired;
ValueAllowed = valueAllowed;
Description = description;
}
}
private static ArgumentDescription[] s_SupportedArguments = new ArgumentDescription[]
{
new ArgumentDescription("/start", false, false, "Starts the application as a service (/start [/silent] [/configFile:<filepath>])."),
new ArgumentDescription("/install", false, false, "Installs the application (/install [/silent] [/configFile:<filepath>])."),
new ArgumentDescription("/uninstall", false, false, "Uninstalls the application (/uninstall [/silent] [/configFile:<filepath>])."),
new ArgumentDescription("/silent", false, false, "Performs operations without prompting user to confirm or displaying errors."),
new ArgumentDescription("/configFile", true, true, "Specifies the installation configuration file."),
};
#endregion
#region Protected Methods
/// <summary>
/// Gets the descriptions for the supported arguments.
/// </summary>
protected virtual ArgumentDescription[] GetArgumentDescriptions()
{
return s_SupportedArguments;
}
/// <summary>
/// Gets the help string.
/// </summary>
protected virtual string GetHelpString(ArgumentDescription[] commands)
{
StringBuilder text = new StringBuilder();
text.Append("These are the supported arguments:\r\n");
for (int ii = 0; ii < commands.Length; ii++)
{
ArgumentDescription command = commands[ii];
text.Append("\r\n");
if (command.ValueRequired)
{
text.AppendFormat("{0}:<value> {1}", command.Name, command.Description);
}
else if (command.ValueAllowed)
{
text.AppendFormat("{0}[:<value>] {1}", command.Name, command.Description);
}
else
{
text.AppendFormat("{0} {1}", command.Name, command.Description);
}
}
text.Append("\r\n");
return text.ToString();
}
/// <summary>
/// Validates the arguments.
/// </summary>
protected virtual string ValidateArguments(bool ignoreUnknownArguments, Dictionary<string, string> args)
{
ArgumentDescription[] commands = GetArgumentDescriptions();
// check if help was requested.
if (args.ContainsKey("/?"))
{
return GetHelpString(commands);
}
// validate the arguments.
StringBuilder error = new StringBuilder();
foreach (KeyValuePair<string, string> arg in args)
{
ArgumentDescription command = null;
for (int ii = 0; ii < commands.Length; ii++)
{
if (String.Compare(commands[ii].Name, arg.Key, StringComparison.OrdinalIgnoreCase) == 0)
{
command = commands[ii];
break;
}
}
if (command == null)
{
if (!ignoreUnknownArguments)
{
if (error.Length > 0)
{
error.Append("\r\n");
}
error.AppendFormat("Unrecognized argument: {0}", arg.Key);
}
continue;
}
if (command.ValueRequired && String.IsNullOrEmpty(arg.Value))
{
if (error.Length > 0)
{
error.Append("\r\n");
}
error.AppendFormat("{0} requires a value to be specified (syntax {0}:<value>).", arg.Key);
continue;
}
if (!command.ValueAllowed && !String.IsNullOrEmpty(arg.Value))
{
if (error.Length > 0)
{
error.Append("\r\n");
}
error.AppendFormat("{0} does not allow a value to be specified.", arg.Key);
continue;
}
}
// return any error text.
return error.ToString();
}
/// <summary>
/// Updates the application configuration with the values from the installation configuration.
/// </summary>
/// <param name="configuration">The configuration to update.</param>
protected virtual void UpdateAppConfigWithInstallConfig(ApplicationConfiguration configuration)
{
// override the application name.
if (InstallConfig.ApplicationName != null)
{
if (configuration.SecurityConfiguration != null && configuration.SecurityConfiguration.ApplicationCertificate != null)
{
if (configuration.SecurityConfiguration.ApplicationCertificate.SubjectName == configuration.ApplicationName)
{
configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = InstallConfig.ApplicationName;
}
}
configuration.ApplicationName = InstallConfig.ApplicationName;
}
if (InstallConfig.ApplicationUri != null)
{
configuration.ApplicationUri = InstallConfig.ApplicationUri;
}
// replace localhost with the current machine name.
if (configuration.ApplicationUri != null)
{
int index = configuration.ApplicationUri.IndexOf("localhost", StringComparison.OrdinalIgnoreCase);
if (index != -1)
{
StringBuilder buffer = new StringBuilder();
buffer.Append(configuration.ApplicationUri.Substring(0, index));
buffer.Append(System.Net.Dns.GetHostName());
buffer.Append(configuration.ApplicationUri.Substring(index + "localhost".Length));
configuration.ApplicationUri = buffer.ToString();
}
}
ServerBaseConfiguration serverConfiguration = null;
if (configuration.ServerConfiguration != null)
{
serverConfiguration = configuration.ServerConfiguration;
}
else if (configuration.DiscoveryServerConfiguration != null)
{
serverConfiguration = configuration.DiscoveryServerConfiguration;
}
if (serverConfiguration != null)
{
if (InstallConfig.BaseAddresses != null && InstallConfig.BaseAddresses.Count > 0)
{
Dictionary<string, string> addresses = new Dictionary<string, string>();
serverConfiguration.BaseAddresses.Clear();
for (int ii = 0; ii < InstallConfig.BaseAddresses.Count; ii++)
{
Uri url = Utils.ParseUri(InstallConfig.BaseAddresses[ii]);
if (url != null)
{
if (!addresses.ContainsKey(url.Scheme))
{
serverConfiguration.BaseAddresses.Add(url.ToString());
addresses.Add(url.Scheme, String.Empty);
}
else
{
serverConfiguration.AlternateBaseAddresses.Add(url.ToString());
}
}
}
}
if (InstallConfig.SecurityProfiles != null && InstallConfig.SecurityProfiles.Count > 0)
{
ServerSecurityPolicyCollection securityPolicies = new ServerSecurityPolicyCollection();
for (int ii = 0; ii < InstallConfig.SecurityProfiles.Count; ii++)
{
for (int jj = 0; jj < serverConfiguration.SecurityPolicies.Count; jj++)
{
if (serverConfiguration.SecurityPolicies[jj].SecurityPolicyUri == InstallConfig.SecurityProfiles[ii].ProfileUri)
{
securityPolicies.Add(serverConfiguration.SecurityPolicies[jj]);
}
}
}
serverConfiguration.SecurityPolicies = securityPolicies;
}
}
if (InstallConfig.ApplicationCertificate != null)
{
configuration.SecurityConfiguration.ApplicationCertificate.StoreType = InstallConfig.ApplicationCertificate.StoreType;
configuration.SecurityConfiguration.ApplicationCertificate.StorePath = InstallConfig.ApplicationCertificate.StorePath;
if (String.IsNullOrEmpty(InstallConfig.ApplicationCertificate.SubjectName))
{
configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = InstallConfig.ApplicationCertificate.SubjectName;
}
}
if (InstallConfig.RejectedCertificatesStore != null)
{
configuration.SecurityConfiguration.RejectedCertificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(InstallConfig.RejectedCertificatesStore);
}
if (InstallConfig.IssuerCertificateStore != null)
{
configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = InstallConfig.IssuerCertificateStore.StoreType;
configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = InstallConfig.IssuerCertificateStore.StorePath;
configuration.SecurityConfiguration.TrustedIssuerCertificates.ValidationOptions = (CertificateValidationOptions)(int)InstallConfig.IssuerCertificateStore.ValidationOptions;
}
if (InstallConfig.TrustedCertificateStore != null)
{
configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = InstallConfig.TrustedCertificateStore.StoreType;
configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = InstallConfig.TrustedCertificateStore.StorePath;
configuration.SecurityConfiguration.TrustedPeerCertificates.ValidationOptions = (CertificateValidationOptions)(int)InstallConfig.TrustedCertificateStore.ValidationOptions;
}
configuration.CertificateValidator.Update(configuration);
}
/// <summary>
/// Installs the service.
/// </summary>
/// <param name="silent">if set to <c>true</c> no dialogs such be displayed.</param>
/// <param name="args">Additional arguments provided on the command line.</param>
protected virtual void Install(bool silent, Dictionary<string, string> args)
{
Utils.Trace(Utils.TraceMasks.Information, "Installing application.");
// check the configuration.
string filePath = Utils.GetAbsoluteFilePath(InstallConfig.ConfigurationFile, true, false, false);
if (filePath == null)
{
Utils.Trace("WARNING: Could not load config file specified in the installation configuration: {0}", InstallConfig.ConfigurationFile);
filePath = ApplicationConfiguration.GetFilePathFromAppConfig(ConfigSectionName);
InstallConfig.ConfigurationFile = filePath;
}
ApplicationConfiguration configuration = LoadAppConfig(silent, filePath, Opc.Ua.Security.SecuredApplication.FromApplicationType(InstallConfig.ApplicationType), ConfigurationType, false);
if (configuration == null)
{
return;
}
// update the configuration.
UpdateAppConfigWithInstallConfig(configuration);
ApplicationConfiguration = configuration;
// update configuration with information form the install config.
// check the certificate.
X509Certificate2 certificate = configuration.SecurityConfiguration.ApplicationCertificate.Find(true);
if (certificate != null)
{
if (!silent)
{
if (!CheckApplicationInstanceCertificate(configuration, certificate, silent, InstallConfig.MinimumKeySize))
{
certificate = null;
}
}
}
// create a new certificate.
if (certificate == null)
{
certificate = CreateApplicationInstanceCertificate(configuration, InstallConfig.MinimumKeySize, InstallConfig.LifeTimeInMonths);
}
// ensure the certificate is trusted.
AddToTrustedStore(configuration, certificate);
// add to discovery server.
if (configuration.ApplicationType == ApplicationType.Server || configuration.ApplicationType == ApplicationType.ClientAndServer)
{
try
{
AddToDiscoveryServerTrustList(certificate, null, null, configuration.SecurityConfiguration.TrustedPeerCertificates);
}
catch (Exception e)
{
Utils.Trace(e, "Could not add certificate to LDS trust list.");
}
}
// configure HTTP access.
ConfigureHttpAccess(configuration, false);
// configure access to the executable, the configuration file and the private key.
ConfigureFileAccess(configuration);
// update configuration file.
ConfigUtils.UpdateConfigurationLocation(InstallConfig.ExecutableFile, InstallConfig.ConfigurationFile);
try
{
// ensure the RawData does not get serialized.
certificate = configuration.SecurityConfiguration.ApplicationCertificate.Certificate;
configuration.SecurityConfiguration.ApplicationCertificate.Certificate = null;
configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = certificate.Subject;
configuration.SecurityConfiguration.ApplicationCertificate.Thumbprint = certificate.Thumbprint;
configuration.SaveToFile(configuration.SourceFilePath);
// restore the configuration.
configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate;
}
catch (Exception e)
{
Utils.Trace(e, "Could not save configuration file. FilePath={0}", configuration.SourceFilePath);
}
if (!NoGdsAgentAdmin)
{
try
{
// install the GDS agent configuration file
string agentPath = Utils.GetAbsoluteDirectoryPath("%CommonApplicationData%\\OPC Foundation\\GDS\\Applications", false, false, true);
if (agentPath != null)
{
Opc.Ua.Security.SecuredApplication export = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configuration.SourceFilePath);
export.ExecutableFile = InstallConfig.ExecutableFile;
DataContractSerializer serializer = new DataContractSerializer(typeof(Opc.Ua.Security.SecuredApplication));
using (FileStream ostrm = File.Open(agentPath + "\\" + configuration.ApplicationName + ".xml", FileMode.Create))
{
serializer.WriteObject(ostrm, export);
Utils.Trace(Utils.TraceMasks.Information, "Created GDS agent configuration file.");
}
}
}
catch (Exception e)
{
Utils.Trace(Utils.TraceMasks.Error, "Could not create GDS agent configuration file: {0}", e.Message);
}
}
// install the service.
if (InstallConfig.InstallAsService)
{
Utils.Trace(Utils.TraceMasks.Information, "Installing service '{0}'.", InstallConfig.ApplicationName);
OnBeforeInstallService();
bool start = true;
bool result = Opc.Ua.Configuration.ServiceInstaller.InstallService(
Application.ExecutablePath,
InstallConfig.ApplicationName,
configuration.ApplicationName,
InstallConfig.ServiceDescription,
InstallConfig.ServiceStartMode,
InstallConfig.ServiceUserName,
InstallConfig.ServicePassword,
ref start);
if (!result)
{
throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "Could not install service.");
}
Utils.Trace(Utils.TraceMasks.Information, "Service '{0}' installed as {1}.", InstallConfig.ApplicationName, InstallConfig.ServiceStartMode);
}
}
/// <summary>
/// Called immediately before the service is installed.
/// </summary>
protected virtual void OnBeforeInstallService()
{
// can be overridden in child class.
}
/// <summary>
/// Uninstalls the service.
/// </summary>
/// <param name="silent">if set to <c>true</c> no dialogs such be displayed.</param>
/// <param name="args">Additional arguments provided on the command line.</param>
protected virtual void Uninstall(bool silent, Dictionary<string, string> args)
{
// check the configuration.
string filePath = Utils.GetAbsoluteFilePath(InstallConfig.ConfigurationFile, true, false, false);
if (filePath == null)
{
Utils.Trace("WARNING: Could not load config file specified in the installation configuration: {0}", InstallConfig.ConfigurationFile);
filePath = ApplicationConfiguration.GetFilePathFromAppConfig(ConfigSectionName);
InstallConfig.ConfigurationFile = filePath;
}
ApplicationConfiguration configuration = LoadAppConfig(silent, filePath, Opc.Ua.Security.SecuredApplication.FromApplicationType(InstallConfig.ApplicationType), ConfigurationType, false);
ApplicationConfiguration = configuration;
if (configuration != null)
{
// configure HTTP access.
ConfigureHttpAccess(configuration, true);
// delete certificate.
if (InstallConfig.DeleteCertificatesOnUninstall)
{
DeleteApplicationInstanceCertificate(configuration);
}
}
if (InstallConfig.InstallAsService)
{
if (!Opc.Ua.Configuration.ServiceInstaller.UnInstallService(InstallConfig.ApplicationName))
{
Utils.Trace("Service could not be uninstalled.");
}
}
if (!NoGdsAgentAdmin)
{
try
{
string agentPath = Utils.GetAbsoluteDirectoryPath("%CommonApplicationData%\\OPC Foundation\\GDS\\Applications", false, false, false);
if (agentPath != null)
{
File.Delete(agentPath + "\\" + configuration.ApplicationName + ".xml");
}
}
catch (Exception e)
{
Utils.Trace(Utils.TraceMasks.Error, "Could not create GDS agent configuration file: {0}", e.Message);
}
}
}
/// <summary>
/// Processes the command.
/// </summary>
/// <param name="silent">if set to <c>true</c> no dialogs such be displayed.</param>
/// <param name="args">Additional arguments provided on the command line.</param>
/// <returns>True if the command was processed.</returns>
protected virtual bool ProcessCommand(bool silent, Dictionary<string, string> args)
{
return false;
}
#endregion
#region Static Methods
/// <summary>
/// Loads the configuration.
/// </summary>
public static ApplicationConfiguration LoadAppConfig(
bool silent,
string filePath,
ApplicationType applicationType,
Type configurationType,
bool applyTraceSettings)
{
Utils.Trace(Utils.TraceMasks.Information, "Loading application configuration file. {0}", filePath);
try
{
// load the configuration file.
ApplicationConfiguration configuration = ApplicationConfiguration.Load(
new System.IO.FileInfo(filePath),
applicationType,
configurationType,
applyTraceSettings);
if (configuration == null)
{
return null;
}
return configuration;
}
catch (Exception e)
{
// warn user.
if (!silent)
{
ExceptionDlg.Show("Load Application Configuration", e);
}
Utils.Trace(e, "Could not load configuration file. {0}", filePath);
return null;
}
}
/// <summary>
/// Loads the application configuration.
/// </summary>
public ApplicationConfiguration LoadApplicationConfiguration(string filePath, bool silent)
{
ApplicationConfiguration configuration = LoadAppConfig(silent, filePath, ApplicationType, ConfigurationType, true);
if (configuration == null)
{
throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "Could not load configuration file.");
}
m_applicationConfiguration = configuration;
return configuration;
}
/// <summary>
/// Loads the application configuration.
/// </summary>
public ApplicationConfiguration LoadApplicationConfiguration(bool silent)
{
string filePath = ApplicationConfiguration.GetFilePathFromAppConfig(ConfigSectionName);
ApplicationConfiguration configuration = LoadAppConfig(silent, filePath, ApplicationType, ConfigurationType, true);
if (configuration == null)
{
throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "Could not load configuration file.");
}
m_applicationConfiguration = configuration;
return configuration;
}
/// <summary>
/// Checks for a valid application instance certificate.
/// </summary>
/// <param name="silent">if set to <c>true</c> no dialogs will be displayed.</param>
/// <param name="minimumKeySize">Minimum size of the key.</param>
public void CheckApplicationInstanceCertificate(
bool silent,
ushort minimumKeySize)
{
Utils.Trace(Utils.TraceMasks.Information, "Checking application instance certificate.");
ApplicationConfiguration configuration = null;
if (m_applicationConfiguration == null)
{
LoadApplicationConfiguration(silent);
}
configuration = m_applicationConfiguration;
bool createNewCertificate = true;
// find the existing certificate.
CertificateIdentifier id = configuration.SecurityConfiguration.ApplicationCertificate;
if (id == null)
{
throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "Configuration file does not specify a certificate.");
}
X509Certificate2 certificate = id.Find(true);
// check that it is ok.
if (certificate != null)
{
createNewCertificate = !CheckApplicationInstanceCertificate(configuration, certificate, silent, minimumKeySize);
}
else
{
// check for missing private key.
certificate = id.Find(false);
if (certificate != null)
{
throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "Cannot access certificate private key. Subject={0}", certificate.Subject);
}
// check for missing thumbprint.
if (!String.IsNullOrEmpty(id.Thumbprint))
{
if (!String.IsNullOrEmpty(id.SubjectName))
{
CertificateIdentifier id2 = new CertificateIdentifier();
id2.StoreType = id.StoreType;
id2.StorePath = id.StorePath;
id2.SubjectName = id.SubjectName;
certificate = id2.Find(true);
}
if (certificate != null)
{
string message = Utils.Format(
"Thumbprint was explicitly specified in the configuration." +
"\r\nAnother certificate with the same subject name was found." +
"\r\nUse it instead?\r\n" +
"\r\nRequested: {0}" +
"\r\nFound: {1}",
id.SubjectName,
certificate.Subject);
throw ServiceResultException.Create(StatusCodes.BadConfigurationError, message);
}
else
{
string message = Utils.Format("Thumbprint was explicitly specified in the configuration. Cannot generate a new certificate.");
throw ServiceResultException.Create(StatusCodes.BadConfigurationError, message);
}
}
else
{
if (String.IsNullOrEmpty(id.SubjectName))
{
string message = Utils.Format("Both SubjectName and Thumbprint are not specified in the configuration. Cannot generate a new certificate.");
throw ServiceResultException.Create(StatusCodes.BadConfigurationError, message);
}
}
}
// create a new certificate.
if (createNewCertificate)
{
certificate = CreateApplicationInstanceCertificate(configuration, minimumKeySize, 600);
}
// ensure it is trusted.
else
{
AddToTrustedStore(configuration, certificate);
}
// add to discovery server.
if (configuration.ApplicationType == ApplicationType.Server || configuration.ApplicationType == ApplicationType.ClientAndServer)
{
try
{
AddToDiscoveryServerTrustList(certificate, null, null, configuration.SecurityConfiguration.TrustedPeerCertificates);
}
catch (Exception e)
{
Utils.Trace(e, "Could not add certificate to LDS trust list.");
}
}
}
#endregion
#region HTTPS Support
/// <summary>
/// Uses the UA validation logic for HTTPS certificates.
/// </summary>
/// <param name="validator">The validator.</param>
public static void SetUaValidationForHttps(CertificateValidator validator)
{
m_validator = validator;
System.Net.ServicePointManager.ServerCertificateValidationCallback = HttpsCertificateValidation;
}
/// <summary>
/// Remotes the certificate validate.
/// </summary>
private static bool HttpsCertificateValidation(
object sender,
X509Certificate cert,
X509Chain chain,
System.Net.Security.SslPolicyErrors error)
{
try
{
m_validator.Validate(new X509Certificate2(cert.GetRawCertData()));
return true;
}
catch (Exception e)
{
Utils.Trace(e, "Could not verify SSL certificate: {0}", cert.Subject);
return false;
}
}
private static CertificateValidator m_validator;
#endregion
#region Private Methods
/// <summary>
/// Handles a certificate validation error.
/// </summary>
private static void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e)
{
try
{
if (e.Error != null && e.Error.Code == StatusCodes.BadCertificateUntrusted)
{
e.Accept = true;
Utils.Trace((int)Utils.TraceMasks.Security, "Automatically accepted certificate: {0}", e.Certificate.Subject);
}
}
catch (Exception exception)
{
Utils.Trace(exception, "Error accepting certificate.");
}
}
/// <summary>
/// Creates an application instance certificate if one does not already exist.
/// </summary>
private static bool CheckApplicationInstanceCertificate(
ApplicationConfiguration configuration,
X509Certificate2 certificate,
bool silent,
ushort minimumKeySize)
{
if (certificate == null)
{
return false;
}
Utils.Trace(Utils.TraceMasks.Information, "Checking application instance certificate. {0}", certificate.Subject);
// validate certificate.
configuration.CertificateValidator.Validate(certificate);
// check key size.
if (minimumKeySize > certificate.PublicKey.Key.KeySize)
{
bool valid = false;
string message = Utils.Format(
"The key size ({0}) in the certificate is less than the minimum provided ({1}). Update certificate?",
certificate.PublicKey.Key.KeySize,
minimumKeySize);
if (!silent)
{
if (MessageBox.Show(message, configuration.ApplicationName, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes)
{
valid = true;
}
}
Utils.Trace(message);
if (!valid)
{
return false;
}
}
// check domains.
if (configuration.ApplicationType != ApplicationType.Client)
{
if (!CheckDomainsInCertificate(configuration, certificate, silent))
{
return false;
}
}
// update uri.
string applicationUri = Utils.GetApplicationUriFromCertficate(certificate);
if (String.IsNullOrEmpty(applicationUri))
{
bool valid = false;
string message = "The Application URI is not specified in the certificate. Update certificate?";
if (!silent)
{
if (MessageBox.Show(message, configuration.ApplicationName, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes)
{
valid = true;
}
}
Utils.Trace(message);
if (!valid)
{
return false;
}
}
// update configuration.
configuration.ApplicationUri = applicationUri;
configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate;
return true;
}
/// <summary>
/// Checks that the domains in the server addresses match the domains in the certificates.
/// </summary>
private static bool CheckDomainsInCertificate(
ApplicationConfiguration configuration,
X509Certificate2 certificate,
bool silent)
{
Utils.Trace(Utils.TraceMasks.Information, "Checking domains in certificate. {0}", certificate.Subject);
bool valid = true;
IList<string> serverDomainNames = configuration.GetServerDomainNames();
IList<string> certificateDomainNames = Utils.GetDomainsFromCertficate(certificate);
// get computer name.
string computerName = System.Net.Dns.GetHostName();
// get DNS aliases and IP addresses.
System.Net.IPHostEntry entry = System.Net.Dns.GetHostEntry(computerName);
for (int ii = 0; ii < serverDomainNames.Count; ii++)
{
if (Utils.FindStringIgnoreCase(certificateDomainNames, serverDomainNames[ii]))
{
continue;
}
if (String.Compare(serverDomainNames[ii], "localhost", StringComparison.OrdinalIgnoreCase) == 0)
{
if (Utils.FindStringIgnoreCase(certificateDomainNames, computerName))
{
continue;
}
// check for aliases.
bool found = false;
for (int jj = 0; jj < entry.Aliases.Length; jj++)
{
if (Utils.FindStringIgnoreCase(certificateDomainNames, entry.Aliases[jj]))
{
found = true;
break;
}
}
if (found)
{
continue;
}
// check for ip addresses.
for (int jj = 0; jj < entry.AddressList.Length; jj++)
{
if (Utils.FindStringIgnoreCase(certificateDomainNames, entry.AddressList[jj].ToString()))
{
found = true;
break;
}
}
if (found)
{
continue;
}
}
string message = Utils.Format(
"The server is configured to use domain '{0}' which does not appear in the certificate. Update certificate?",
serverDomainNames[ii]);
valid = false;
if (!silent)
{
if (MessageBox.Show(message, configuration.ApplicationName, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes)
{
valid = true;
continue;
}
}
Utils.Trace(message);
break;
}
return valid;
}
/// <summary>
/// Creates the application instance certificate.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="keySize">Size of the key.</param>
/// <param name="lifetimeInMonths">The lifetime in months.</param>
/// <returns>The new certificate</returns>
private static X509Certificate2 CreateApplicationInstanceCertificate(
ApplicationConfiguration configuration,
ushort keySize,
ushort lifetimeInMonths)
{
Utils.Trace(Utils.TraceMasks.Information, "Creating application instance certificate. KeySize={0}, Lifetime={1}", keySize, lifetimeInMonths);
// delete existing any existing certificate.
DeleteApplicationInstanceCertificate(configuration);
CertificateIdentifier id = configuration.SecurityConfiguration.ApplicationCertificate;
// get the domains from the configuration file.
IList<string> serverDomainNames = configuration.GetServerDomainNames();
if (serverDomainNames.Count == 0)
{
serverDomainNames.Add(System.Net.Dns.GetHostName());
}
// ensure the certificate store directory exists.
if (id.StoreType == CertificateStoreType.Directory)
{
Utils.GetAbsoluteDirectoryPath(id.StorePath, true, true, true);
}
X509Certificate2 certificate = Opc.Ua.CertificateFactory.CreateCertificate(
id.StoreType,
id.StorePath,
configuration.ApplicationUri,
configuration.ApplicationName,
null,
serverDomainNames,
keySize,
lifetimeInMonths);
id.Certificate = certificate;
AddToTrustedStore(configuration, certificate);
/*
if (id.StoreType == CertificateStoreType.Directory)
{
DirectoryCertificateStore store = new DirectoryCertificateStore();
store.Open(id.StorePath);
List<ApplicationAccessRule> rules = new List<ApplicationAccessRule>();
ApplicationAccessRule 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);
rule = new ApplicationAccessRule();
rule.RuleType = AccessControlType.Allow;
rule.Right = ApplicationAccessRight.Run;
rule.IdentityName = WellKnownSids.LocalSystem;
rules.Add(rule);
store.SetAccessRules(certificate.Thumbprint, rules, false);
}
*/
configuration.CertificateValidator.Update(configuration.SecurityConfiguration);
Utils.Trace(Utils.TraceMasks.Information, "Certificate created. Thumbprint={0}", certificate.Thumbprint);
// reload the certificate from disk.
return configuration.SecurityConfiguration.ApplicationCertificate.LoadPrivateKey(null);
}
/// <summary>
/// Deletes an existing application instance certificate.
/// </summary>
/// <param name="configuration">The configuration instance that stores the configurable information for a UA application.</param>
private static void DeleteApplicationInstanceCertificate(ApplicationConfiguration configuration)
{
Utils.Trace(Utils.TraceMasks.Information, "Deleting application instance certificate.");
// create a default certificate id none specified.
CertificateIdentifier id = configuration.SecurityConfiguration.ApplicationCertificate;
if (id == null)
{
return;
}
// delete private key.
X509Certificate2 certificate = id.Find();
// delete trusted peer certificate.
if (configuration.SecurityConfiguration != null && configuration.SecurityConfiguration.TrustedPeerCertificates != null)
{
string thumbprint = id.Thumbprint;
if (certificate != null)
{
thumbprint = certificate.Thumbprint;
}
using (ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore())
{
store.Delete(thumbprint);
}
}
// delete private key.
if (certificate != null)
{
using (ICertificateStore store = id.OpenStore())
{
store.Delete(certificate.Thumbprint);
}
}
}
/// <summary>
/// Adds the application certificate to the discovery server trust list.
/// </summary>
public static void AddToDiscoveryServerTrustList(
X509Certificate2 certificate,
string oldThumbprint,
IList<X509Certificate2> issuers,
CertificateStoreIdentifier trustedCertificateStore)
{
Utils.Trace(Utils.TraceMasks.Information, "Adding certificate to discovery server trust list.");
try
{
string configurationPath = Utils.GetAbsoluteFilePath(@"%CommonApplicationData%\OPC Foundation\Config\Opc.Ua.DiscoveryServer.Config.xml", true, false, false);
if (configurationPath == null)
{
return;
//throw new ServiceResultException("Could not find the discovery server configuration file. Please confirm that it is installed.");
}
Opc.Ua.Security.SecuredApplication ldsConfiguration = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationPath);
CertificateStoreIdentifier csid = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(ldsConfiguration.TrustedCertificateStore);
AddApplicationCertificateToStore(csid, certificate, oldThumbprint);
if (issuers != null && ldsConfiguration.IssuerCertificateStore != null)
{
csid = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(ldsConfiguration.IssuerCertificateStore);
AddIssuerCertificatesToStore(csid, issuers);
}
CertificateIdentifier cid = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(ldsConfiguration.ApplicationCertificate);
X509Certificate2 ldsCertificate = cid.Find(false);
// add LDS certificate to application trust list.
if (ldsCertificate != null && trustedCertificateStore != null)
{
AddApplicationCertificateToStore(csid, ldsCertificate, null);
}
}
catch (Exception e)
{
Utils.Trace(e, "Could not add certificate to discovery server trust list.");
}
}
/// <summary>
/// Adds an application certificate to a store.
/// </summary>
private static void AddApplicationCertificateToStore(
CertificateStoreIdentifier csid,
X509Certificate2 certificate,
string oldThumbprint)
{
ICertificateStore store = csid.OpenStore();
try
{
// delete the old certificate.
if (oldThumbprint != null)
{
store.Delete(oldThumbprint);
}
// delete certificates with the same application uri.
if (store.FindByThumbprint(certificate.Thumbprint) == null)
{
string applicationUri = Utils.GetApplicationUriFromCertficate(certificate);
// delete any existing certificates.
foreach (X509Certificate2 target in store.Enumerate())
{
if (Utils.CompareDistinguishedName(target.Subject, certificate.Subject))
{
if (Utils.GetApplicationUriFromCertficate(target) == applicationUri)
{
store.Delete(target.Thumbprint);
}
}
}
// add new certificate.
store.Add(new X509Certificate2(certificate.RawData));
}
}
finally
{
store.Close();
}
}
/// <summary>
/// Adds an application certificate to a store.
/// </summary>
private static void AddIssuerCertificatesToStore(CertificateStoreIdentifier csid, IList<X509Certificate2> issuers)
{
ICertificateStore store = csid.OpenStore();
try
{
foreach (X509Certificate2 issuer in issuers)
{
if (store.FindByThumbprint(issuer.Thumbprint) == null)
{
store.Add(issuer);
}
}
}
finally
{
store.Close();
}
}
/// <summary>
/// Adds the certificate to the Trusted Certificate Store
/// </summary>
/// <param name="configuration">The application's configuration which specifies the location of the TrustedStore.</param>
/// <param name="certificate">The certificate to register.</param>
private static void AddToTrustedStore(ApplicationConfiguration configuration, X509Certificate2 certificate)
{
string storePath = null;
if (configuration != null && configuration.SecurityConfiguration != null && configuration.SecurityConfiguration.TrustedPeerCertificates != null)
{
storePath = configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath;
}
if (String.IsNullOrEmpty(storePath))
{
Utils.Trace(Utils.TraceMasks.Information, "WARNING: Trusted peer store not specified.");
return;
}
try
{
ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore();
if (store == null)
{
Utils.Trace("Could not open trusted peer store. StorePath={0}", storePath);
return;
}
try
{
// check if it already exists.
X509Certificate2 certificate2 = store.FindByThumbprint(certificate.Thumbprint);
if (certificate2 != null)
{
return;
}
Utils.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", storePath);
List<string> subjectName = Utils.ParseDistinguishedName(certificate.Subject);
// check for old certificate.
X509Certificate2Collection certificates = store.Enumerate();
for (int ii = 0; ii < certificates.Count; ii++)
{
if (Utils.CompareDistinguishedName(certificates[ii], subjectName))
{
if (certificates[ii].Thumbprint == certificate.Thumbprint)
{
return;
}
store.Delete(certificates[ii].Thumbprint);
break;
}
}
// add new certificate.
X509Certificate2 publicKey = new X509Certificate2(certificate.GetRawCertData());
store.Add(publicKey);
}
finally
{
store.Close();
}
}
catch (Exception e)
{
Utils.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", storePath);
}
}
/// <summary>
/// Configures the HTTP access.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="remove">if set to <c>true</c> then the HTTP access should be removed.</param>
private void ConfigureHttpAccess(ApplicationConfiguration configuration, bool remove)
{
Utils.Trace(Utils.TraceMasks.Information, "Configuring HTTP access.");
// check for HTTP endpoints which need configuring.
StringCollection baseAddresses = new StringCollection();
if (configuration.DiscoveryServerConfiguration != null)
{
baseAddresses = configuration.DiscoveryServerConfiguration.BaseAddresses;
}
if (configuration.ServerConfiguration != null)
{
baseAddresses = configuration.ServerConfiguration.BaseAddresses;
}
// configure WCF http access.
for (int ii = 0; ii < baseAddresses.Count; ii++)
{
string url = GetHttpUrlForAccessRule(baseAddresses[ii]);
if (url != null)
{
SetHttpAccessRules(url, remove);
}
}
}
/// <summary>
/// Gets the HTTP URL to use for HTTP access rules.
/// </summary>
public static string GetHttpUrlForAccessRule(string baseAddress)
{
Uri url = Utils.ParseUri(baseAddress);
if (url == null)
{
return null;
}
UriBuilder builder = new UriBuilder(url);
switch (url.Scheme)
{
case Utils.UriSchemeHttps:
{
builder.Path = String.Empty;
builder.Query = String.Empty;
break;
}
case Utils.UriSchemeNoSecurityHttp:
{
builder.Scheme = Utils.UriSchemeHttp;
builder.Path = String.Empty;
builder.Query = String.Empty;
break;
}
case Utils.UriSchemeHttp:
{
break;
}
default:
{
return null;
}
}
return builder.ToString();
}
/// <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>
/// Sets the HTTP access rules for the URL.
/// </summary>
private void SetHttpAccessRules(string url, bool remove)
{
try
{
List<ApplicationAccessRule> rules = new List<ApplicationAccessRule>();
if (!remove)
{
rules = GetAccessRules();
}
HttpAccessRule.SetAccessRules(new Uri(url), rules, false);
}
catch (Exception e)
{
Utils.Trace(e, "Unexpected configuring the HTTP access rules.");
}
}
/// <summary>
/// Configures access to the executable, the configuration file and the private key.
/// </summary>
private void ConfigureFileAccess(ApplicationConfiguration configuration)
{
Utils.Trace(Utils.TraceMasks.Information, "Configuring file access.");
List<ApplicationAccessRule> rules = GetAccessRules();
// apply access rules to the excutable file.
try
{
if (InstallConfig.SetExecutableFilePermissions)
{
ApplicationAccessRule.SetAccessRules(InstallConfig.ExecutableFile, rules, true);
}
}
catch (Exception e)
{
Utils.Trace(e, "Could not set executable file permissions.");
}
// apply access rules to the configuration file.
try
{
if (InstallConfig.SetConfigurationFilePermisions)
{
ApplicationAccessRule.SetAccessRules(configuration.SourceFilePath, rules, true);
}
}
catch (Exception e)
{
Utils.Trace(e, "Could not set configuration file permissions.");
}
// apply access rules to the private key file.
try
{
X509Certificate2 certificate = configuration.SecurityConfiguration.ApplicationCertificate.Find(true);
if (certificate != null)
{
ICertificateStore store = configuration.SecurityConfiguration.ApplicationCertificate.OpenStore();
store.SetAccessRules(certificate.Thumbprint, rules, true);
}
}
catch (Exception e)
{
Utils.Trace(e, "Could not set private key file permissions.");
}
}
#endregion
#region Private Fields
private string m_applicationName;
private ApplicationType m_applicationType;
private string m_configSectionName;
private Type m_configurationType;
private InstalledApplication m_installConfig;
private ServerBase m_server;
private ApplicationConfiguration m_applicationConfiguration;
#endregion
}
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/lishilei0523-h-opc.git
git@gitlife.ru:oschina-mirror/lishilei0523-h-opc.git
oschina-mirror
lishilei0523-h-opc
lishilei0523-h-opc
master