/// <summary> /// Returns the domain names which the server is configured to use. /// </summary> /// <returns>A list of domain names.</returns> public IList <string> GetServerDomainNames() { StringCollection baseAddresses = new StringCollection(); if (this.ServerConfiguration != null) { if (this.ServerConfiguration.BaseAddresses != null) { baseAddresses.AddRange(this.ServerConfiguration.BaseAddresses); } if (this.ServerConfiguration.AlternateBaseAddresses != null) { baseAddresses.AddRange(this.ServerConfiguration.AlternateBaseAddresses); } } if (this.DiscoveryServerConfiguration != null) { if (this.DiscoveryServerConfiguration.BaseAddresses != null) { baseAddresses.AddRange(this.DiscoveryServerConfiguration.BaseAddresses); } if (this.DiscoveryServerConfiguration.AlternateBaseAddresses != null) { baseAddresses.AddRange(this.DiscoveryServerConfiguration.AlternateBaseAddresses); } } var domainNames = new List <string>(); for (int ii = 0; ii < baseAddresses.Count; ii++) { Uri url = Utils.ParseUri(baseAddresses[ii]); if (url == null) { continue; } string domainName = url.DnsSafeHost; if (url.HostNameType == UriHostNameType.Dns) { domainName = Utils.ReplaceLocalhost(domainName); } else // IPv4/IPv6 address { domainName = Utils.NormalizedIPAddress(domainName); } if (!Utils.FindStringIgnoreCase(domainNames, domainName)) { domainNames.Add(domainName); } } return(domainNames); }
/// <summary> /// Patch returned endpoints urls with url used to reached the endpoint. /// </summary> private EndpointDescriptionCollection PatchEndpointUrls(EndpointDescriptionCollection endpoints) { // if a server is behind a firewall, can only be accessed with a FQDN or IP address // it may return URLs that are not accessible to the client. This problem can be avoided // by assuming that the domain in the URL used to call GetEndpoints can be used to // access any of the endpoints. This code patches the returned endpoints accordingly. Uri endpointUrl = Utils.ParseUri(this.Endpoint.EndpointUrl); if (endpointUrl != null) { // patch discovery Url to endpoint Url used for service call foreach (EndpointDescription discoveryEndPoint in endpoints) { Uri discoveryEndPointUri = Utils.ParseUri(discoveryEndPoint.EndpointUrl); if (endpointUrl.Scheme == discoveryEndPointUri.Scheme) { UriBuilder builder = new UriBuilder(discoveryEndPointUri); builder.Host = endpointUrl.DnsSafeHost; builder.Port = endpointUrl.Port; discoveryEndPoint.EndpointUrl = builder.ToString(); } if (discoveryEndPoint.Server != null && discoveryEndPoint.Server.DiscoveryUrls != null) { discoveryEndPoint.Server.DiscoveryUrls.Clear(); discoveryEndPoint.Server.DiscoveryUrls.Add(this.Endpoint.EndpointUrl.ToString()); } } } return(endpoints); }
/// <summary> /// Adds the discovery url to the hosts. /// </summary> /// <param name="configuration">The configuration.</param> /// <param name="discoveryUrls">The discovery urls.</param> public virtual void InitializeDiscovery( ApplicationConfiguration configuration, StringCollection discoveryUrls) { // create the binding factory. BindingFactory bindingFactory = BindingFactory.Create(configuration, configuration.CreateMessageContext()); EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration); foreach (string discoveryUrl in discoveryUrls) { // parse discovery url. Uri url = Utils.ParseUri(discoveryUrl); if (url == null) { continue; } // create endpoint. if (url.PathAndQuery.EndsWith("/discovery")) { Binding binding = bindingFactory.Create(url.Scheme, endpointConfiguration); this.AddServiceEndpoint(typeof(IDiscoveryEndpoint), binding, url, url); } } }
/// <summary> /// Creates a configured endpoint from the server description. /// </summary> public ConfiguredEndpoint( ApplicationDescription server, EndpointConfiguration configuration) { if (server == null) { throw new ArgumentNullException("server"); } m_description = new EndpointDescription(); m_updateBeforeConnect = true; m_description.Server = server; foreach (string discoveryUrl in server.DiscoveryUrls) { string baseUrl = discoveryUrl; if (baseUrl != null) { if (baseUrl.EndsWith("/discovery", StringComparison.Ordinal)) { baseUrl = baseUrl.Substring(0, baseUrl.Length - "/discovery".Length); } } Uri url = Utils.ParseUri(baseUrl); if (url != null) { // MY EDITS TO TRY MAKING WORK WITH USERNAME m_description.EndpointUrl = url.ToString(); m_description.SecurityMode = MessageSecurityMode.None; // MessageSecurityMode.SignAndEncrypt; m_description.SecurityPolicyUri = SecurityPolicies.None; //SecurityPolicies.Basic128Rsa15; m_description.UserIdentityTokens.Add(new UserTokenPolicy(UserTokenType.UserName)); // Anonymous)); if (url.Scheme == Utils.UriSchemeHttps) { m_description.TransportProfileUri = Profiles.HttpsBinaryTransport; } if (url.Scheme == Utils.UriSchemeOpcTcp) { m_description.TransportProfileUri = Profiles.UaTcpTransport; } break; } } // ensure a default configuration. if (configuration == null) { configuration = EndpointConfiguration.Create(); } Update(configuration); }
/// <summary> /// Returns the domain names which the server is configured to use. /// </summary> /// <returns>A list of domain names.</returns> public IList <string> GetServerDomainNames() { List <string> domainNames = new List <string>(); StringCollection baseAddresses = new StringCollection(); if (this.ServerConfiguration != null) { if (this.ServerConfiguration.BaseAddresses != null) { baseAddresses.AddRange(this.ServerConfiguration.BaseAddresses); } if (this.ServerConfiguration.AlternateBaseAddresses != null) { baseAddresses.AddRange(this.ServerConfiguration.AlternateBaseAddresses); } } if (this.DiscoveryServerConfiguration != null) { if (this.DiscoveryServerConfiguration.BaseAddresses != null) { baseAddresses.AddRange(this.DiscoveryServerConfiguration.BaseAddresses); } if (this.DiscoveryServerConfiguration.AlternateBaseAddresses != null) { baseAddresses.AddRange(this.DiscoveryServerConfiguration.AlternateBaseAddresses); } } for (int ii = 0; ii < baseAddresses.Count; ii++) { Uri url = Utils.ParseUri(baseAddresses[ii]); if (url == null) { continue; } string domainName = url.DnsSafeHost; if (String.Compare(domainName, "localhost", StringComparison.OrdinalIgnoreCase) == 0) { domainName = Utils.GetHostName(); } if (!Utils.FindStringIgnoreCase(domainNames, domainName)) { domainNames.Add(domainName); } } return(domainNames); }
/// <summary> /// Returns a discovery url that can be used to update the endpoint description. /// </summary> public Uri GetDiscoveryUrl(Uri endpointUrl) { // update the endpoint description. if (endpointUrl != null) { m_description.EndpointUrl = endpointUrl.ToString(); } else { endpointUrl = Utils.ParseUri(m_description.EndpointUrl); } // get the know discovery URLs. StringCollection discoveryUrls = null; if (m_description.Server != null) { discoveryUrls = m_description.Server.DiscoveryUrls; } // attempt to construct a discovery url by appending 'discovery' to the endpoint. if (discoveryUrls == null || discoveryUrls.Count == 0) { if (endpointUrl.Scheme != Utils.UriSchemeOpcTcp) { return(new Uri(String.Format(CultureInfo.InvariantCulture, "{0}/discovery", endpointUrl))); } else { return(endpointUrl); } } // choose the URL that uses the same protocol if one exists. for (int ii = 1; ii < discoveryUrls.Count; ii++) { if (discoveryUrls[ii].StartsWith(endpointUrl.Scheme, StringComparison.Ordinal)) { return(Utils.ParseUri(discoveryUrls[ii])); } } // return the first in the list. return(Utils.ParseUri(discoveryUrls[0])); }
/// <summary> /// Sets the parameters to suitable defaults. /// </summary> private static void SetSuitableDefaults( ref string applicationUri, ref string applicationName, ref string subjectName, ref IList <String> domainNames, ref ushort keySize, ref ushort lifetimeInMonths, bool isCA) { // enforce recommended keysize unless lower value is enforced. if (keySize < 1024) { keySize = defaultKeySize; } if (keySize % 1024 != 0) { throw new ArgumentNullException("keySize", "KeySize must be a multiple of 1024."); } // enforce minimum lifetime. if (lifetimeInMonths < 1) { lifetimeInMonths = 1; } // parse the subject name if specified. List <string> subjectNameEntries = null; if (!String.IsNullOrEmpty(subjectName)) { subjectNameEntries = Utils.ParseDistinguishedName(subjectName); } // check the application name. if (String.IsNullOrEmpty(applicationName)) { if (subjectNameEntries == null) { throw new ArgumentNullException("applicationName", "Must specify a applicationName or a subjectName."); } // use the common name as the application name. for (int ii = 0; ii < subjectNameEntries.Count; ii++) { if (subjectNameEntries[ii].StartsWith("CN=")) { applicationName = subjectNameEntries[ii].Substring(3).Trim(); break; } } } // remove special characters from name. StringBuilder buffer = new StringBuilder(); for (int ii = 0; ii < applicationName.Length; ii++) { char ch = applicationName[ii]; if (Char.IsControl(ch) || ch == '/' || ch == ',' || ch == ';') { ch = '+'; } buffer.Append(ch); } applicationName = buffer.ToString(); // ensure at least one host name. if (domainNames == null || domainNames.Count == 0) { domainNames = new List <string>(); domainNames.Add(Utils.GetHostName()); } // create the application uri. if (String.IsNullOrEmpty(applicationUri)) { StringBuilder builder = new StringBuilder(); builder.Append("urn:"); builder.Append(domainNames[0]); builder.Append(":"); builder.Append(applicationName); applicationUri = builder.ToString(); } Uri uri = Utils.ParseUri(applicationUri); if (uri == null) { throw new ArgumentNullException("applicationUri", "Must specify a valid URL."); } // create the subject name, if (String.IsNullOrEmpty(subjectName)) { subjectName = Utils.Format("CN={0}/DC={1}", applicationName, domainNames[0]); } }
/// <summary> /// Updates an endpoint with information from the server's discovery endpoint. /// </summary> public void UpdateFromServer( Uri endpointUrl, MessageSecurityMode securityMode, string securityPolicyUri) { // get the a discovery url. Uri discoveryUrl = GetDiscoveryUrl(endpointUrl); // create the discovery client. DiscoveryClient client = DiscoveryClient.Create(discoveryUrl, m_configuration); try { // get the endpoints. EndpointDescriptionCollection collection = client.GetEndpoints(null); if (collection == null || collection.Count == 0) { throw ServiceResultException.Create( StatusCodes.BadUnknownResponse, "Server does not have any endpoints defined."); } // find list of matching endpoints. EndpointDescriptionCollection matches = new EndpointDescriptionCollection(); // first pass - match on the requested security parameters. foreach (EndpointDescription description in collection) { // check for match on security policy. if (!String.IsNullOrEmpty(securityPolicyUri)) { if (securityPolicyUri != description.SecurityPolicyUri) { continue; } } // check for match on security mode. if (securityMode != MessageSecurityMode.Invalid) { if (securityMode != description.SecurityMode) { continue; } } // add to list of matches. matches.Add(description); } // no matches (security parameters may have changed). if (matches.Count == 0) { matches = collection; } // check if list has to be narrowed down further. if (matches.Count > 1) { collection = matches; matches = new EndpointDescriptionCollection(); // second pass - match on the url scheme. foreach (EndpointDescription description in collection) { // parse the endpoint url. Uri sessionUrl = Utils.ParseUri(description.EndpointUrl); if (sessionUrl == null) { continue; } // check for matching protocol. if (sessionUrl.Scheme != endpointUrl.Scheme) { continue; } matches.Add(description); } } // no matches (protocol may not be supported). if (matches.Count == 0) { matches = collection; } // choose first in list by default. EndpointDescription match = matches[0]; // check if list has to be narrowed down further. if (matches.Count > 1) { // third pass - match based on security level. foreach (EndpointDescription description in matches) { if (description.SecurityMode > match.SecurityMode) { match = description; } } } // check if the endpoint url matches the endpoint used in the request. Uri matchUrl = Utils.ParseUri(match.EndpointUrl); if (matchUrl == null || String.Compare(discoveryUrl.DnsSafeHost, matchUrl.DnsSafeHost, StringComparison.OrdinalIgnoreCase) != 0) { UriBuilder uri = new UriBuilder(matchUrl); uri.Host = discoveryUrl.DnsSafeHost; uri.Port = discoveryUrl.Port; match.EndpointUrl = uri.ToString(); // need to update the discovery urls. match.Server.DiscoveryUrls.Clear(); match.Server.DiscoveryUrls.Add(discoveryUrl.ToString()); } // update the endpoint. Update(match); } finally { client.Close(); } }
/// <summary> /// Sets the parameters to suitable defaults. /// </summary> private static void SetSuitableDefaults( ref string applicationUri, ref string applicationName, ref string subjectName, ref IList <String> domainNames) { // parse the subject name if specified. List <string> subjectNameEntries = null; if (!String.IsNullOrEmpty(subjectName)) { subjectNameEntries = X509Utils.ParseDistinguishedName(subjectName); } // check the application name. if (String.IsNullOrEmpty(applicationName)) { if (subjectNameEntries == null) { throw new ArgumentNullException(nameof(applicationName), "Must specify a applicationName or a subjectName."); } // use the common name as the application name. for (int ii = 0; ii < subjectNameEntries.Count; ii++) { if (subjectNameEntries[ii].StartsWith("CN=", StringComparison.Ordinal)) { applicationName = subjectNameEntries[ii].Substring(3).Trim(); break; } } } if (String.IsNullOrEmpty(applicationName)) { throw new ArgumentNullException(nameof(applicationName), "Must specify a applicationName or a subjectName."); } // remove special characters from name. StringBuilder buffer = new StringBuilder(); for (int ii = 0; ii < applicationName.Length; ii++) { char ch = applicationName[ii]; if (Char.IsControl(ch) || ch == '/' || ch == ',' || ch == ';') { ch = '+'; } buffer.Append(ch); } applicationName = buffer.ToString(); // ensure at least one host name. if (domainNames == null || domainNames.Count == 0) { domainNames = new List <string>(); domainNames.Add(Utils.GetHostName()); } // create the application uri. if (String.IsNullOrEmpty(applicationUri)) { StringBuilder builder = new StringBuilder(); builder.Append("urn:"); builder.Append(domainNames[0]); builder.Append(':'); builder.Append(applicationName); applicationUri = builder.ToString(); } Uri uri = Utils.ParseUri(applicationUri); if (uri == null) { throw new ArgumentNullException(nameof(applicationUri), "Must specify a valid URL."); } // create the subject name, if (String.IsNullOrEmpty(subjectName)) { subjectName = Utils.Format("CN={0}", applicationName); } if (!subjectName.Contains("CN=")) { subjectName = Utils.Format("CN={0}", subjectName); } if (domainNames != null && domainNames.Count > 0) { if (!subjectName.Contains("DC=") && !subjectName.Contains('=')) { subjectName += Utils.Format(", DC={0}", domainNames[0]); } else { subjectName = Utils.ReplaceDCLocalhost(subjectName, domainNames[0]); } } }