/// <summary> /// Activates the session. /// </summary> public byte[] Activate( SignatureData signature, ListOfString localeIds, ExtensionObject userIdentityToken, SignatureData userTokenSignature) { lock (m_lock) { if (m_clientCertificate != null) { // validate the client's signature. byte[] dataToSign = SecurityUtils.Append(m_endpoint.ServerCertificate, m_serverNonce); bool valid = SecurityUtils.Verify( m_clientCertificate, m_endpoint.SecurityPolicyUri, dataToSign, signature); if (!valid) { throw new StatusCodeException( StatusCodes.BadSecurityChecksFailed, "Client did not provide a correct signature for the nonce data provided by the server."); } } m_activated = true; m_localeIds = localeIds; // TBD - validate the user identity token. // return a new nonce. RNGCryptoServiceProvider random = new RNGCryptoServiceProvider(); random.GetBytes(m_serverNonce); return(m_serverNonce); } }
/// <summary> /// Creates a session with the server that is independent of the network connection. /// </summary> public CreateSessionResponseMessage CreateSession(CreateSessionMessage request) { try { lock (m_lock) { InitializeApplicationDescription(); // create a new session object. Session session = new Session(); NodeId sessionId; NodeId authenticationToken; byte[] serverNonce; double revisedSessionTimeout; EndpointDescription endpoint = m_endpoints[0]; // the session object validates the incoming parameters and produces faults on error. session.Create( endpoint, request.ClientDescription, request.ClientCertificate, request.SessionName, request.RequestedSessionTimeout, out sessionId, out authenticationToken, out serverNonce, out revisedSessionTimeout); // save the session. m_sessions.Add(authenticationToken.Identifier, session); // the server application must authenticate itself to the client by providing a signature. // this process is redundant for applications using WS-SecureConversation with mutual certificate // exchange, however, the UA specification requires this step to ensure that secure channel // technologies such as machine-to-machine VPNs can be used instead without sacrificing the // ability to identify the remote applications. byte[] dataToSign = SecurityUtils.Append(request.ClientCertificate, request.ClientNonce); SignatureData serverSignature = SecurityUtils.Sign( m_serverCertificate, endpoint.SecurityPolicyUri, dataToSign); // contruct the response. CreateSessionResponseMessage response = new CreateSessionResponseMessage(); response.ResponseHeader = CreateResponseHeader(request.RequestHeader); response.SessionId = sessionId; response.AuthenticationToken = authenticationToken; response.MaxRequestMessageSize = request.MaxResponseMessageSize; response.RevisedSessionTimeout = revisedSessionTimeout; response.ServerNonce = serverNonce; response.ServerCertificate = m_serverCertificate.GetRawCertData(); response.ServerSignature = serverSignature; response.ServerEndpoints = m_endpoints; response.ServerSoftwareCertificates = new ListOfSignedSoftwareCertificate(); return(response); } } catch (Exception e) { throw CreateSoapFault(request.RequestHeader, e); } }
/// <summary> /// Creates a session with the server. /// </summary> public void CreateSession() { ApplicationDescription description = new ApplicationDescription(); description.ApplicationName = new LocalizedText("UA Sample Client"); description.ApplicationType = ApplicationType.Client_1; description.ApplicationUri = "http://localhost/UASampleClient"; byte[] serverCertificateData; ListOfEndpointDescription serverEndpoints; ListOfSignedSoftwareCertificate serverSoftwareCertificates; SignatureData serverSignature; // create a client nonce. byte[] clientNonce = new byte[32]; RNGCryptoServiceProvider random = new RNGCryptoServiceProvider(); random.GetBytes(clientNonce); string endpointUrl = this.Endpoint.Address.Uri.ToString(); // create the session. CreateSession( CreateRequestHeader(), description, null, this.Endpoint.Address.Uri.ToString(), "My Session", clientNonce, m_clientCertificate.RawData, 600000, 0, out m_sessionId, out m_authenticationToken, out m_sessionTimeout, out m_serverNonce, out serverCertificateData, out serverEndpoints, out serverSoftwareCertificates, out serverSignature, out m_maxRequestMessageSize); // find the endpoint description being used. string securityPolicyUri = ""; Uri url = new Uri(endpointUrl); foreach (EndpointDescription serverEndpoint in serverEndpoints) { Uri url2 = new Uri(serverEndpoint.EndpointUrl); if (url2.Scheme == url.Scheme && url2.Port == url.Port && url2.PathAndQuery == url.PathAndQuery) { securityPolicyUri = serverEndpoint.SecurityPolicyUri; break; } } // validate the server's signature. byte[] dataToSign = SecurityUtils.Append(m_clientCertificate.RawData, clientNonce); bool valid = SecurityUtils.Verify( new X509Certificate2(serverCertificateData), securityPolicyUri, dataToSign, serverSignature); if (!valid) { throw new StatusCodeException( StatusCodes.BadSecurityChecksFailed, "Server did not provide a correct signature for the nonce data provided by the client."); } // create the client signature. dataToSign = SecurityUtils.Append(serverCertificateData, m_serverNonce); SignatureData clientSignature = SecurityUtils.Sign( m_clientCertificate, securityPolicyUri, dataToSign); // use an anonymous user identity token. ExtensionObject userIdentityToken = new ExtensionObject( new ExpandedNodeId(Objects.AnonymousIdentityToken_Encoding_DefaultXml), new AnonymousIdentityToken()); ListOfStatusCode results; ListOfDiagnosticInfo diagnosticInfos; // activate the session. ActivateSession( CreateRequestHeader(), clientSignature, new ListOfSignedSoftwareCertificate(), new ListOfString(), null, null, out m_serverNonce, out results, out diagnosticInfos); }