Opc.Ua.Client.Session.Open C# (CSharp) Method

Open() private method

private Open ( string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, bool checkDomain ) : void
sessionName string
sessionTimeout uint
identity IUserIdentity
preferredLocales IList
checkDomain bool
return void
        public void Open(
            string        sessionName,
            uint          sessionTimeout,
            IUserIdentity identity,
            IList<string> preferredLocales,
            bool          checkDomain)
        {
            // check connection state.
            lock (SyncRoot)
            {
                if (Connected)
                {
                    throw new ServiceResultException(StatusCodes.BadInvalidState, "Already connected to server.");
                }
            }

            string securityPolicyUri = m_endpoint.Description.SecurityPolicyUri;

            // get the identity token.            
            if (identity == null)
            {
                identity = new UserIdentity();
            }

            // get identity token.
            UserIdentityToken identityToken = identity.GetIdentityToken();

            // check that the user identity is supported by the endpoint.
            UserTokenPolicy identityPolicy = m_endpoint.Description.FindUserTokenPolicy(identityToken.PolicyId);

            if (identityPolicy == null)
            {
                // try looking up by TokenType if the policy id was not found.
                identityPolicy = m_endpoint.Description.FindUserTokenPolicy(identity.TokenType, identity.IssuedTokenType);

                if (identityPolicy == null)
                {
                    throw ServiceResultException.Create(
                        StatusCodes.BadUserAccessDenied,
                        "Endpoint does not supported the user identity type provided.");
                }

                identityToken.PolicyId = identityPolicy.PolicyId;
            }

            bool requireEncryption = securityPolicyUri != SecurityPolicies.None;

            if (!requireEncryption)
            {
                requireEncryption = identityPolicy.SecurityPolicyUri != SecurityPolicies.None && 
                    !String.IsNullOrEmpty(identityPolicy.SecurityPolicyUri);
            }

            // validate the server certificate.
            X509Certificate2 serverCertificate = null;
            byte[] certificateData = m_endpoint.Description.ServerCertificate;

            if (certificateData != null && certificateData.Length > 0 && requireEncryption)
            {
                serverCertificate = Utils.ParseCertificateBlob(certificateData);
                m_configuration.CertificateValidator.Validate(serverCertificate);

                if(checkDomain)
                {
                    CheckCertificateDomain(m_endpoint);
                }

                //X509Certificate2Collection certificateChain = Utils.ParseCertificateChainBlob(certificateData);                
                //if (certificateChain.Count > 0)
                //    serverCertificate = certificateChain[0];
                //m_configuration.CertificateValidator.Validate(certificateChain);
            }

            // create a nonce.
            byte[] clientNonce = new byte[m_configuration.SecurityConfiguration.NonceLength];
            new RNGCryptoServiceProvider().GetBytes(clientNonce);
            
                        
            NodeId sessionId = null;
            NodeId sessionCookie = null;
            byte[] serverNonce = new byte[0];
            byte[] serverCertificateData = new byte[0];
            SignatureData serverSignature = null;
            EndpointDescriptionCollection serverEndpoints = null;
            SignedSoftwareCertificateCollection serverSoftwareCertificates = null;
                                   
            // send the application instance certificate for the client.
            byte[] clientCertificateData = m_instanceCertificate != null ? m_instanceCertificate.RawData : null;

            //byte[] clientCertificateData = null;
            //if (m_instanceCertificateChain != null)
            //{
            //    List<byte> clientCertificateChainData = new List<byte>();
            //    for (int i = 0; i < m_instanceCertificateChain.Count; i++)
            //    {
            //        clientCertificateChainData.AddRange(m_instanceCertificateChain[i].RawData);
            //    }

            //    clientCertificateData = clientCertificateChainData.ToArray();
            //}
                                
            ApplicationDescription clientDescription = new ApplicationDescription();

            clientDescription.ApplicationUri  = m_configuration.ApplicationUri;
            clientDescription.ApplicationName = m_configuration.ApplicationName;
            clientDescription.ApplicationType = ApplicationType.Client;
            clientDescription.ProductUri      = m_configuration.ProductUri;
            
            if (sessionTimeout == 0)
            {
                sessionTimeout = (uint)m_configuration.ClientConfiguration.DefaultSessionTimeout;
            }

            bool successCreateSession = false;
            //if security none, first try to connect without certificate
            if (m_endpoint.Description.SecurityPolicyUri == SecurityPolicies.None)
            {
                //first try to connect with client certificate NULL
                try
                {
                    CreateSession(
                        null,
                        clientDescription,
                        m_endpoint.Description.Server.ApplicationUri,
                        m_endpoint.EndpointUrl.ToString(),
                        sessionName,
                        clientNonce,
                        null,
                        sessionTimeout,
                        (uint)MessageContext.MaxMessageSize,
                        out sessionId,
                        out sessionCookie,
                        out m_sessionTimeout,
                        out serverNonce,
                        out serverCertificateData,
                        out serverEndpoints,
                        out serverSoftwareCertificates,
                        out serverSignature,
                        out m_maxRequestMessageSize);

                    successCreateSession = true;
                }
                catch(Exception ex)
                {
                    Utils.Trace("Create session failed with client certificate NULL. " + ex.Message);
                    successCreateSession = false;
                }
            }

            if (!successCreateSession)
            {
                CreateSession(
                        null,
                        clientDescription,
                        m_endpoint.Description.Server.ApplicationUri,
                        m_endpoint.EndpointUrl.ToString(),
                        sessionName,
                        clientNonce,
                        clientCertificateData,
                        sessionTimeout,
                        (uint)MessageContext.MaxMessageSize,
                        out sessionId,
                        out sessionCookie,
                        out m_sessionTimeout,
                        out serverNonce,
                        out serverCertificateData,
                        out serverEndpoints,
                        out serverSoftwareCertificates,
                        out serverSignature,
                        out m_maxRequestMessageSize);

            }
            // save session id.
            lock (SyncRoot)
            {
                base.SessionCreated(sessionId, sessionCookie);
            }

            Utils.Trace("Revised session timeout value: {0}. ", m_sessionTimeout);
            Utils.Trace("Max response message size value: {0}. Max request message size: {1} ", MessageContext.MaxMessageSize, m_maxRequestMessageSize);

			//we need to call CloseSession if CreateSession was successful but some other exception is thrown
			try
			{

				// verify that the server returned the same instance certificate.
                if (serverCertificateData != null && !Utils.IsEqual(serverCertificateData, m_endpoint.Description.ServerCertificate))
				{
					throw ServiceResultException.Create(
						StatusCodes.BadCertificateInvalid,
						"Server did not return the certificate used to create the secure channel." );
				}

                if (serverSignature == null || serverSignature.Signature == null)
                {
                    Utils.Trace("Server signature is null or empty.");

                    //throw ServiceResultException.Create(
                    //    StatusCodes.BadSecurityChecksFailed,
                    //    "Server signature is null or empty.");
                }

                if (m_expectedServerEndpoints != null && m_expectedServerEndpoints.Count > 0)
                {
                    // verify that the list of endpoints returned by CreateSession matches the list returned at GetEndpoints.
                    if (m_expectedServerEndpoints.Count != serverEndpoints.Count)
                    {
                        throw ServiceResultException.Create(
                            StatusCodes.BadSecurityChecksFailed,
                            "Server did not return a number of ServerEndpoints that matches the one from GetEndpoints.");
                    }

                    for (int ii = 0; ii < serverEndpoints.Count; ii++)
                    {
                        EndpointDescription serverEndpoint = serverEndpoints[ii];
                        EndpointDescription expectedServerEndpoint = m_expectedServerEndpoints[ii];

                        if (serverEndpoint.SecurityMode != expectedServerEndpoint.SecurityMode ||
                            serverEndpoint.SecurityPolicyUri != expectedServerEndpoint.SecurityPolicyUri ||
                            serverEndpoint.TransportProfileUri != expectedServerEndpoint.TransportProfileUri ||
                            serverEndpoint.SecurityLevel != expectedServerEndpoint.SecurityLevel)
                        {
                            throw ServiceResultException.Create(
                                StatusCodes.BadSecurityChecksFailed,
                                "The list of ServerEndpoints returned at CreateSession does not match the list from GetEndpoints.");
                        }

                        if (serverEndpoint.UserIdentityTokens.Count != expectedServerEndpoint.UserIdentityTokens.Count)
                        {
                            throw ServiceResultException.Create(
                                StatusCodes.BadSecurityChecksFailed,
                                "The list of ServerEndpoints returned at CreateSession does not match the one from GetEndpoints.");
                        }

                        for (int jj = 0; jj < serverEndpoint.UserIdentityTokens.Count; jj++)
                        {
                            if (!serverEndpoint.UserIdentityTokens[jj].IsEqual(expectedServerEndpoint.UserIdentityTokens[jj]))
                            {
                                throw ServiceResultException.Create(
                                StatusCodes.BadSecurityChecksFailed,
                                "The list of ServerEndpoints returned at CreateSession does not match the one from GetEndpoints.");
                            }
                        }
                    }
                }


				// find the matching description (TBD - check domains against certificate).
				bool found = false;
				Uri expectedUrl = Utils.ParseUri( m_endpoint.Description.EndpointUrl );

                if (expectedUrl != null)
                {
                    for (int ii = 0; ii < serverEndpoints.Count; ii++)
                    {
                        EndpointDescription serverEndpoint = serverEndpoints[ii];
                        Uri actualUrl = Utils.ParseUri(serverEndpoint.EndpointUrl);

                        if (actualUrl != null && actualUrl.Scheme == expectedUrl.Scheme)
                        {
                            if (serverEndpoint.SecurityPolicyUri == m_endpoint.Description.SecurityPolicyUri)
                            {
                                if (serverEndpoint.SecurityMode == m_endpoint.Description.SecurityMode)
                                {
                                    // ensure endpoint has up to date information.
                                    m_endpoint.Description.Server.ApplicationName = serverEndpoint.Server.ApplicationName;
                                    m_endpoint.Description.Server.ApplicationUri = serverEndpoint.Server.ApplicationUri;
                                    m_endpoint.Description.Server.ApplicationType = serverEndpoint.Server.ApplicationType;
                                    m_endpoint.Description.Server.ProductUri = serverEndpoint.Server.ProductUri;
                                    m_endpoint.Description.TransportProfileUri = serverEndpoint.TransportProfileUri;
                                    m_endpoint.Description.UserIdentityTokens = serverEndpoint.UserIdentityTokens;

                                    found = true;
                                    break;
                                }
                            }
                        }
                    }
                }

				// could be a security risk.
				if( !found )
				{
					throw ServiceResultException.Create(
						StatusCodes.BadSecurityChecksFailed,
						"Server did not return an EndpointDescription that matched the one used to create the secure channel." );
				}

				// validate the server's signature.
				byte[] dataToSign = Utils.Append( clientCertificateData, clientNonce );

                if (!SecurityPolicies.Verify(serverCertificate, m_endpoint.Description.SecurityPolicyUri, dataToSign, serverSignature))
				{
					throw ServiceResultException.Create(
						StatusCodes.BadApplicationSignatureInvalid,
						"Server did not provide a correct signature for the nonce data provided by the client." );
				}

				// get a validator to check certificates provided by server.
				CertificateValidator validator = m_configuration.CertificateValidator;

				// validate software certificates.
				List<SoftwareCertificate> softwareCertificates = new List<SoftwareCertificate>();

				foreach( SignedSoftwareCertificate signedCertificate in serverSoftwareCertificates )
				{
					SoftwareCertificate softwareCertificate = null;

					ServiceResult result = SoftwareCertificate.Validate(
						validator,
						signedCertificate.CertificateData,
						out softwareCertificate );

					if( ServiceResult.IsBad( result ) )
					{
						OnSoftwareCertificateError( signedCertificate, result );
					}

					softwareCertificates.Add( softwareCertificate );
				}

				// check if software certificates meet application requirements.
				ValidateSoftwareCertificates( softwareCertificates );

				// create the client signature.
				dataToSign = Utils.Append( serverCertificateData, serverNonce );
				SignatureData clientSignature = SecurityPolicies.Sign( m_instanceCertificate, securityPolicyUri, dataToSign );

                // select the security policy for the user token.
                securityPolicyUri = identityPolicy.SecurityPolicyUri;

                if (String.IsNullOrEmpty(securityPolicyUri))
                {
                    securityPolicyUri = m_endpoint.Description.SecurityPolicyUri;
                }

				// sign data with user token.
				SignatureData userTokenSignature = identityToken.Sign( dataToSign, securityPolicyUri );

				// encrypt token.
				identityToken.Encrypt( serverCertificate, serverNonce, securityPolicyUri );

				// send the software certificates assigned to the client.
				SignedSoftwareCertificateCollection clientSoftwareCertificates = GetSoftwareCertificates();

				// copy the preferred locales if provided.
				if( preferredLocales != null && preferredLocales.Count > 0 )
				{
					m_preferredLocales = new StringCollection( preferredLocales );
				}

				StatusCodeCollection certificateResults = null;
				DiagnosticInfoCollection certificateDiagnosticInfos = null;

				// activate session.
				ActivateSession(
					null,
					clientSignature,
					clientSoftwareCertificates,
					m_preferredLocales,
					new ExtensionObject( identityToken ),
					userTokenSignature,
					out serverNonce,
					out certificateResults,
					out certificateDiagnosticInfos );

                if (certificateResults != null)
                {
                    for (int i = 0; i < certificateResults.Count; i++)
                    {
                        Utils.Trace("ActivateSession result[{0}] = {1}", i, certificateResults[i]);    
                    }
                }

                if (certificateResults == null || certificateResults.Count == 0)
                {
                    Utils.Trace("Empty results were received for the ActivateSession call.");
                }

				// fetch namespaces.
				FetchNamespaceTables();

				lock( SyncRoot )
				{
					// save nonces.
					m_sessionName = sessionName;
					m_identity = identity;
					m_serverNonce = serverNonce;
					m_serverCertificate = serverCertificate;

					// update system context.
					m_systemContext.PreferredLocales = m_preferredLocales;
					m_systemContext.SessionId = this.SessionId;
					m_systemContext.UserIdentity = identity;
				}

            // start keep alive thread.
            StartKeepAliveTimer();
			}
			catch
			{
				try
				{
					CloseSession( null, false );
					CloseChannel();
				}
				catch(Exception e)
				{
                    Utils.Trace("Cleanup: CloseSession() or CloseChannel() raised exception. " + e.Message);
				}
				finally
				{
					SessionCreated( null, null );
				}

				throw;
			}
        }

Same methods

Session::Open ( string sessionName, IUserIdentity identity ) : void
Session::Open ( string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales ) : void

Usage Example

Beispiel #1
0
        /// <summary>
        /// Creates a new session.
        /// </summary>
        private Session CreateSession()
        {
            try
            {
                Cursor = Cursors.WaitCursor;

                ServiceMessageContext messageContext = m_configuration.CreateMessageContext();
                BindingFactory bindingFactory = BindingFactory.Create(m_configuration, messageContext);

                ConfiguredEndpoint endpoint = this.EndpointsCTRL.SelectedEndpoint;
                
                endpoint.UpdateFromServer(bindingFactory);
                                
                // Initialize the channel which will be created with the server.
                ITransportChannel channel = SessionChannel.Create(
                    m_configuration,
                    endpoint.Description,
                    endpoint.Configuration,
                    m_configuration.SecurityConfiguration.ApplicationCertificate.Find(true),
                    messageContext);

                // Wrap the channel with the session object.
                Session session = new Session(channel, m_configuration, endpoint, null);

                // Create the session. This actually connects to the server.
                session.Open(Guid.NewGuid().ToString(), null);

                return session;
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
All Usage Examples Of Opc.Ua.Client.Session::Open