/// <summary> /// Verify user token signature /// </summary> /// <param name="userTokenSignature"></param> /// <param name="token"></param> /// <param name="securityPolicyUri"></param> private void VerifyUserTokenSignature(SignatureData userTokenSignature, UserIdentityToken token, string securityPolicyUri) { // Verify with leaf certificate var dataToSign = Utils.Append(_serverCertificate.RawData, _serverNonce); if (token.Verify(dataToSign, userTokenSignature, securityPolicyUri)) { return; } // Validate the signature with complete chain var serverCertificateChain = Utils.ParseCertificateChainBlob( Endpoint.ServerCertificate); if (serverCertificateChain.Count <= 1) { throw new ServiceResultException(StatusCodes.BadUserSignatureInvalid, "Invalid user signature!"); } var serverCertificateChainList = new List <byte>(); for (var i = 0; i < serverCertificateChain.Count; i++) { serverCertificateChainList.AddRange( serverCertificateChain[i].RawData); } var serverCertificateChainData = serverCertificateChainList.ToArray(); dataToSign = Utils.Append(serverCertificateChainData, _serverNonce); if (!token.Verify(dataToSign, userTokenSignature, securityPolicyUri)) { throw new ServiceResultException(StatusCodes.BadUserSignatureInvalid, "Invalid user signature!"); } }
/// <summary> /// Convert user identity token to service model /// </summary> /// <param name="token"></param> /// <param name="serializer"></param> /// <returns></returns> public static CredentialModel ToServiceModel(this UserIdentityToken token, IJsonSerializer serializer) { if (token == null) { return(null); // Treat as anonymous } switch (token) { case IssuedIdentityToken it: switch (it.IssuedTokenType) { case IssuedTokenType.JWT: return(new CredentialModel { Type = CredentialType.JwtToken, Value = serializer.FromObject(it.DecryptedTokenData) }); case IssuedTokenType.SAML: // TODO? default: throw new ServiceResultException( StatusCodes.BadNotSupported, $"Token type {it.IssuedTokenType} is not supported"); } case AnonymousIdentityToken ai: return(null); case UserNameIdentityToken un: return(new CredentialModel { Type = CredentialType.UserName, Value = serializer.FromObject(new { user = un.UserName, password = un.DecryptedPassword }) }); case X509IdentityToken x5: return(new CredentialModel { Type = CredentialType.X509Certificate, Value = serializer.FromObject(x5.CertificateData) }); default: throw new ServiceResultException(StatusCodes.BadNotSupported, $"User identity token type {token.GetType()} is unsupported"); } }
private async void Button1_Click(object sender, EventArgs e) { try { var token = txtToken.Text; var applicationId = new Guid(txtApplicationId.Text); var uit = await UserIdentityToken.ParseAsync(token, applicationId); MessageBox.Show("The token was valid, UserId = " + uit.UserId); } catch (Exception ex) { MessageBox.Show($"An error occurred while validating the user identity token: {ex.Message}"); } }
/// <summary> /// Validate user identity /// </summary> /// <param name="newIdentity"></param> /// <param name="userTokenPolicy"></param> /// <returns></returns> private static IUserIdentity ValidateUserIdentity(UserIdentityToken newIdentity, UserTokenPolicy userTokenPolicy) { System.Diagnostics.Contracts.Contract.Ensures(userTokenPolicy != null); try { IUserIdentity identity = null; IUserIdentity effectiveIdentity = null; // Validate the identity token and impersonate user. // TODO // lock (_eventLock) { // if (_impersonateUser != null) { // // var args = new ImpersonateEventArgs(newIdentity, userTokenPolicy); // _impersonateUser(session, args); // // if (ServiceResult.IsBad(args.IdentityValidationError)) { // error = args.IdentityValidationError; // if (ServiceResult.IsBad(error)) { // throw new ServiceResultException(error); // } // } // else { // identity = args.Identity; // return args.EffectiveIdentity; // } // } // } // check for validation error. if (identity == null) { identity = new UserIdentity(newIdentity); } // use the identity as the effectiveIdentity if not provided. return(effectiveIdentity ?? identity); } catch (ServiceResultException) { throw; } catch (Exception e) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, e, "Could not validate user identity token: {0}", newIdentity); } }
protected override OperationContext ValidateRequest(RequestHeader requestHeader, RequestType requestType) { OperationContext context = new OperationContext(requestHeader, requestType); try { context = base.ValidateRequest(requestHeader, requestType); if (requestType != RequestType.Write) { return(context); } // reject all writes if no user provided. if (context.UserIdentity.TokenType == UserTokenType.Anonymous) { // construct translation object with default text. TranslationInfo info = new TranslationInfo( "NoWriteAllowed", "en-US", "Must provide a valid user before calling write."); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadUserAccessDenied, "NoWriteAllowed", Namespaces.OpcUa, new LocalizedText(info))); } UserIdentityToken securityToken = context.UserIdentity.GetIdentityToken(); // check for a user name token. if (!(securityToken is UserNameIdentityToken)) { return(context); } lock (_requestLock) { _contexts.Add(context.RequestId, new ImpersonationContext()); } return(context); } catch (Exception e) { Utils.Trace($"Session Manager Impersonate Exception:\r\n{e.StackTrace}"); } return(context); }
/// <summary> /// This method is called at the being of the thread that processes a request. /// </summary> protected override OperationContext ValidateRequest(RequestHeader requestHeader, RequestType requestType) { OperationContext context = base.ValidateRequest(requestHeader, requestType); if (requestType == RequestType.Write) { // reject all writes if no user provided. if (context.UserIdentity.TokenType == UserTokenType.Anonymous) { // construct translation object with default text. TranslationInfo info = new TranslationInfo( "NoWriteAllowed", "en-US", "Must provide a valid user before calling write."); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadUserAccessDenied, "NoWriteAllowed", Opc.Ua.Gds.Namespaces.OpcUaGds, new LocalizedText(info))); } UserIdentityToken securityToken = context.UserIdentity.GetIdentityToken(); // check for a user name token. UserNameIdentityToken userNameToken = securityToken as UserNameIdentityToken; if (userNameToken != null) { lock (m_lock) { m_contexts.Add(context.RequestId, new ImpersonationContext()); } } } return(context); }
public static BASEAuthenticationResult AuthenticateUserAndSetToken(string username, string password, int?siteUID) { UserIdentityToken token = null; try { token = UserIdentityToken.CreateToken(username, password, siteUID); if (token == null) { return(BASEAuthenticationResult.InvalidUsernameOrPassword); } else if (token.IsExpired) { return(BASEAuthenticationResult.Expired); } else if (token.IsDisabled) { return(BASEAuthenticationResult.Disabled); } else if (!token.IsValidToken) { return(BASEAuthenticationResult.NotValid); } BASE.Web.SessionState.SessionManager.AddUserToken(token); return(BASEAuthenticationResult.Success); } catch (Exception ex) { #if DEBUG throw; #else return(BASEAuthenticationResult.ExceptionCaught); #endif } }
public static UserIdentityToken GetUserToken() { //Get context ready HttpContext context = HttpContext.Current; //Try first gettoing token from session state. May not exist if user logged in in a previous session. UserIdentityToken token = (UserIdentityToken)Get(SessionKeys.UserToken); if (token == null) { //get again from DB BASE.Logging.Logger.Log("Getting UserToken from DB at SessionManager.GetUserToken()", BASE.Logging.LogPriority.Debug, "SESSIONSTATE"); if (context.User == null || !context.User.Identity.IsAuthenticated) { //Anonymous user, so load anonymous usertoken. token = UserIdentityToken.CreateAnonymousToken(SystemManager.Current.AnonymousGuid); } else { //Authenticated user, load the token. token = UserIdentityToken.CreateTokenNoSecCheck(new Guid(context.User.Identity.Name)); } if (token.IsValidToken) { AddUserToken(token); } else { throw new BASEGenericException("Invalid Token"); } } //TODO: Add extra checking/security return(token); }
/// <summary> /// Updates the user identity. /// </summary> /// <returns>true if the new identity is different from the old identity.</returns> private bool UpdateUserIdentity( UserIdentityToken identityToken, IUserIdentity identity, IUserIdentity effectiveIdentity) { if (identityToken == null) { throw new ArgumentNullException("identityToken"); } lock (m_lock) { bool changed = m_effectiveIdentity == null && effectiveIdentity != null; if (m_effectiveIdentity != null) { changed = !m_effectiveIdentity.Equals(effectiveIdentity); } // always save the new identity since it may have additional information that does not affect equality. m_identityToken = identityToken; m_identity = identity; m_effectiveIdentity = effectiveIdentity; // update diagnostics. lock (m_diagnostics) { m_securityDiagnostics.ClientUserIdOfSession = identity.DisplayName; m_securityDiagnostics.AuthenticationMechanism = identity.TokenType.ToString(); m_securityDiagnostics.ClientUserIdHistory.Add(identity.DisplayName); } return(changed); } }
/// <summary> /// Activates the session and binds it to the current secure channel. /// </summary> public void ValidateBeforeActivate( OperationContext context, SignatureData clientSignature, List <SoftwareCertificate> clientSoftwareCertificates, ExtensionObject userIdentityToken, SignatureData userTokenSignature, StringCollection localeIds, byte[] serverNonce, out UserIdentityToken identityToken, out UserTokenPolicy userTokenPolicy) { lock (m_lock) { // verify that a secure channel was specified. if (context.ChannelContext == null) { throw new ServiceResultException(StatusCodes.BadSecureChannelIdInvalid); } // verify that the same security policy has been used. EndpointDescription endpoint = context.ChannelContext.EndpointDescription; if (endpoint.SecurityPolicyUri != m_endpoint.SecurityPolicyUri || endpoint.SecurityMode != m_endpoint.SecurityMode) { throw new ServiceResultException(StatusCodes.BadSecurityPolicyRejected); } // verify the client signature. if (m_clientCertificate != null) { byte[] dataToSign = Utils.Append(m_serverCertificate.RawData, m_serverNonce); //byte[] dataToSign = Utils.Append(m_serverCertificateChain, m_serverNonce); if (!SecurityPolicies.Verify(m_clientCertificate, m_endpoint.SecurityPolicyUri, dataToSign, clientSignature)) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid); } } if (!m_activated) { // must active the session on the channel that was used to create it. if (m_secureChannelId != context.ChannelContext.SecureChannelId) { throw new ServiceResultException(StatusCodes.BadSecureChannelIdInvalid); } } else { // cannot change the certificates after activation. if (clientSoftwareCertificates != null && clientSoftwareCertificates.Count > 0) { throw new ServiceResultException(StatusCodes.BadInvalidArgument); } } // validate the user identity token. identityToken = ValidateUserIdentityToken(userIdentityToken, userTokenSignature, out userTokenPolicy); TraceState("VALIDATED"); } }
/// <summary> /// Activates the session and binds it to the current secure channel. /// </summary> public void ValidateBeforeActivate( OperationContext context, SignatureData clientSignature, List<SoftwareCertificate> clientSoftwareCertificates, ExtensionObject userIdentityToken, SignatureData userTokenSignature, StringCollection localeIds, byte[] serverNonce, out UserIdentityToken identityToken, out UserTokenPolicy userTokenPolicy) { lock (m_lock) { // verify that a secure channel was specified. if (context.ChannelContext == null) { throw new ServiceResultException(StatusCodes.BadSecureChannelIdInvalid); } // verify that the same security policy has been used. EndpointDescription endpoint = context.ChannelContext.EndpointDescription; if (endpoint.SecurityPolicyUri != m_endpoint.SecurityPolicyUri || endpoint.SecurityMode != m_endpoint.SecurityMode) { throw new ServiceResultException(StatusCodes.BadSecurityPolicyRejected); } // verify the client signature. if (m_clientCertificate != null) { byte[] dataToSign = Utils.Append(m_serverCertificate.RawData, m_serverNonce); if (!SecurityPolicies.Verify(m_clientCertificate, m_endpoint.SecurityPolicyUri, dataToSign, clientSignature)) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid); } } if (!m_activated) { // must active the session on the channel that was used to create it. if (m_secureChannelId != context.ChannelContext.SecureChannelId) { throw new ServiceResultException(StatusCodes.BadSecureChannelIdInvalid); } } else { // cannot change the certificates after activation. if (clientSoftwareCertificates != null && clientSoftwareCertificates.Count > 0) { throw new ServiceResultException(StatusCodes.BadInvalidArgument); } } // validate the user identity token. identityToken = ValidateUserIdentityToken(userIdentityToken, userTokenSignature, out userTokenPolicy); TraceState("VALIDATED"); } }
/// <summary> /// Activates the session and binds it to the current secure channel. /// </summary> public bool Activate( OperationContext context, List<SoftwareCertificate> clientSoftwareCertificates, UserIdentityToken identityToken, IUserIdentity identity, IUserIdentity effectiveIdentity, StringCollection localeIds, byte[] serverNonce) { lock (m_lock) { // update user identity. bool changed = false; if (identityToken != null) { if (UpdateUserIdentity(identityToken, identity, effectiveIdentity)) { changed = true; } } // update local ids. if (UpdateLocaleIds( localeIds )) { changed = true; } if (!m_activated) { // toggle the activated flag. m_activated = true; // save the software certificates. m_softwareCertificates = clientSoftwareCertificates; TraceState("FIRST ACTIVATION"); } else { // bind to the new secure channel. m_secureChannelId = context.ChannelContext.SecureChannelId; TraceState("RE-ACTIVATION"); } // update server nonce. m_serverNonce = serverNonce; // build list of signed certificates for audit event. List<SignedSoftwareCertificate> signedSoftwareCertificates = new List<SignedSoftwareCertificate>(); if (clientSoftwareCertificates != null) { foreach (SoftwareCertificate softwareCertificate in clientSoftwareCertificates) { SignedSoftwareCertificate item = new SignedSoftwareCertificate(); item.CertificateData = softwareCertificate.SignedCertificate.RawData; signedSoftwareCertificates.Add(item); } } // raise an audit event. ServerSystemContext systemContext = m_server.DefaultSystemContext.Copy(context); ReportAuditActivateSessionEvent(systemContext); // update the contact time. lock (m_diagnostics) { m_diagnostics.ClientLastContactTime = DateTime.UtcNow; } // indicate whether the user context has changed. return changed; } }
public async Task UserIdentityToken_EmptyGuidApplication() { var token = await UserIdentityToken.ParseAsync("valid token", Guid.Empty); }
/// <summary> /// Updates the user identity. /// </summary> /// <returns>true if the new identity is different from the old identity.</returns> private bool UpdateUserIdentity( UserIdentityToken identityToken, IUserIdentity identity, IUserIdentity effectiveIdentity) { if (identityToken == null) throw new ArgumentNullException("identityToken"); lock (m_lock) { bool changed = m_effectiveIdentity == null && effectiveIdentity != null; if (m_effectiveIdentity != null) { changed = !m_effectiveIdentity.Equals(effectiveIdentity); } // always save the new identity since it may have additional information that does not affect equality. m_identityToken = identityToken; m_identity = identity; m_effectiveIdentity = effectiveIdentity; // update diagnostics. lock (m_diagnostics) { m_securityDiagnostics.ClientUserIdOfSession = identity.DisplayName; m_securityDiagnostics.AuthenticationMechanism = identity.TokenType.ToString(); m_securityDiagnostics.ClientUserIdHistory.Add(identity.DisplayName); } return changed; } }
/// <summary> /// Creates a new instance. /// </summary> public ImpersonateEventArgs(UserIdentityToken newIdentity, UserTokenPolicy userTokenPolicy, EndpointDescription endpointDescription = null) { m_newIdentity = newIdentity; m_userTokenPolicy = userTokenPolicy; m_endpointDescription = endpointDescription; }
/// <summary> /// Activates the session and binds it to the current secure channel. /// </summary> public void ValidateBeforeActivate( OperationContext context, SignatureData clientSignature, List <SoftwareCertificate> clientSoftwareCertificates, ExtensionObject userIdentityToken, SignatureData userTokenSignature, StringCollection localeIds, byte[] serverNonce, out UserIdentityToken identityToken, out UserTokenPolicy userTokenPolicy) { lock (m_lock) { // verify that a secure channel was specified. if (context.ChannelContext == null) { throw new ServiceResultException(StatusCodes.BadSecureChannelIdInvalid); } // verify that the same security policy has been used. EndpointDescription endpoint = context.ChannelContext.EndpointDescription; if (endpoint.SecurityPolicyUri != m_endpoint.SecurityPolicyUri || endpoint.SecurityMode != m_endpoint.SecurityMode) { throw new ServiceResultException(StatusCodes.BadSecurityPolicyRejected); } // verify the client signature. if (m_clientCertificate != null) { if (m_endpoint.SecurityPolicyUri != SecurityPolicies.None && clientSignature != null && clientSignature.Signature == null) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid); } byte[] dataToSign = Utils.Append(m_serverCertificate.RawData, m_serverNonce); if (!SecurityPolicies.Verify(m_clientCertificate, m_endpoint.SecurityPolicyUri, dataToSign, clientSignature)) { // verify for certificate chain in endpoint. // validate the signature with complete chain if the check with leaf certificate failed. X509Certificate2Collection serverCertificateChain = Utils.ParseCertificateChainBlob(m_endpoint.ServerCertificate); if (serverCertificateChain.Count > 1) { List <byte> serverCertificateChainList = new List <byte>(); for (int i = 0; i < serverCertificateChain.Count; i++) { serverCertificateChainList.AddRange(serverCertificateChain[i].RawData); } byte[] serverCertificateChainData = serverCertificateChainList.ToArray(); dataToSign = Utils.Append(serverCertificateChainData, m_serverNonce); if (!SecurityPolicies.Verify(m_clientCertificate, m_endpoint.SecurityPolicyUri, dataToSign, clientSignature)) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid); } } else { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid); } } } if (!m_activated) { // must active the session on the channel that was used to create it. if (m_secureChannelId != context.ChannelContext.SecureChannelId) { throw new ServiceResultException(StatusCodes.BadSecureChannelIdInvalid); } } else { // cannot change the certificates after activation. if (clientSoftwareCertificates != null && clientSoftwareCertificates.Count > 0) { throw new ServiceResultException(StatusCodes.BadInvalidArgument); } } // validate the user identity token. identityToken = ValidateUserIdentityToken(userIdentityToken, userTokenSignature, out userTokenPolicy); TraceState("VALIDATED"); } }
public void UserIdentityToken_Constructor_Success() { var token = new UserIdentityToken(new SigningKeysCache()); }
/// <summary> /// Activates an existing session /// </summary> public virtual bool ActivateSession( OperationContext context, NodeId authenticationToken, SignatureData clientSignature, List <SoftwareCertificate> clientSoftwareCertificates, ExtensionObject userIdentityToken, SignatureData userTokenSignature, StringCollection localeIds, out byte[] serverNonce) { serverNonce = null; Session session = null; UserIdentityToken newIdentity = null; UserTokenPolicy userTokenPolicy = null; lock (m_lock) { // find session. if (!m_sessions.TryGetValue(authenticationToken, out session)) { throw new ServiceResultException(StatusCodes.BadSessionClosed); } // check if session timeout has expired. if (session.HasExpired) { m_server.CloseSession(null, session.Id, false); throw new ServiceResultException(StatusCodes.BadSessionClosed); } // create new server nonce. serverNonce = Utils.Nonce.CreateNonce((uint)m_minNonceLength); // validate before activation. session.ValidateBeforeActivate( context, clientSignature, clientSoftwareCertificates, userIdentityToken, userTokenSignature, localeIds, serverNonce, out newIdentity, out userTokenPolicy); } IUserIdentity identity = null; IUserIdentity effectiveIdentity = null; ServiceResult error = null; try { // check if the application has a callback which validates the identity tokens. lock (m_eventLock) { if (m_ImpersonateUser != null) { ImpersonateEventArgs args = new ImpersonateEventArgs(newIdentity, userTokenPolicy); m_ImpersonateUser(session, args); if (ServiceResult.IsBad(args.IdentityValidationError)) { error = args.IdentityValidationError; } else { identity = args.Identity; effectiveIdentity = args.EffectiveIdentity; } } } // parse the token manually if the identity is not provided. if (identity == null) { identity = new UserIdentity(newIdentity); } // use the identity as the effectiveIdentity if not provided. if (effectiveIdentity == null) { effectiveIdentity = identity; } } catch (Exception e) { if (e is ServiceResultException) { throw e; } throw ServiceResultException.Create( StatusCodes.BadIdentityTokenInvalid, e, "Could not validate user identity token: {0}", newIdentity); } // check for validation error. if (ServiceResult.IsBad(error)) { throw new ServiceResultException(error); } // activate session. bool contextChanged = session.Activate( context, clientSoftwareCertificates, newIdentity, identity, effectiveIdentity, localeIds, serverNonce); // raise session related event. if (contextChanged) { RaiseSessionEvent(session, SessionEventReason.Activated); } // indicates that the identity context for the session has changed. return(contextChanged); }
protected override async Task OnOpenAsync(CancellationToken token) { await base.OnOpenAsync(token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); // if SessionId is provided then we skip the CreateSessionRequest and go directly to (re)ActivateSession. // requires from previous Session: SessionId, AuthenticationToken, RemoteNonce if (this.SessionId == null) { var localNonce = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.GetNextNonce() : null; var localCertificateBlob = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.LocalCertificate.RawData : null; var createSessionRequest = new CreateSessionRequest { ClientDescription = this.LocalDescription, EndpointUrl = this.RemoteEndpoint.EndpointUrl, SessionName = this.LocalDescription.ApplicationName, ClientNonce = localNonce, ClientCertificate = localCertificateBlob, RequestedSessionTimeout = this.SessionTimeout, MaxResponseMessageSize = this.RemoteMaxMessageSize }; var createSessionResponse = await this.CreateSessionAsync(createSessionRequest).ConfigureAwait(false); this.SessionId = createSessionResponse.SessionId; this.AuthenticationToken = createSessionResponse.AuthenticationToken; this.RemoteNonce = createSessionResponse.ServerNonce; // verify the server's certificate is the same as the certificate from the selected endpoint. if (this.RemoteEndpoint.ServerCertificate != null && !this.RemoteEndpoint.ServerCertificate.SequenceEqual(createSessionResponse.ServerCertificate)) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Server did not return the same certificate used to create the channel."); } // verify the server's signature. switch (this.RemoteEndpoint.SecurityPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: byte[] dataToVerify = Concat(localCertificateBlob, localNonce); if (!this.RemotePublicKey.VerifyData(dataToVerify, createSessionResponse.ServerSignature.Signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1)) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client."); } break; case SecurityPolicyUris.Basic256Sha256: byte[] dataToVerify256 = Concat(localCertificateBlob, localNonce); if (!this.RemotePublicKey.VerifyData(dataToVerify256, createSessionResponse.ServerSignature.Signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client."); } break; default: break; } } // create client signature SignatureData clientSignature = null; switch (this.RemoteEndpoint.SecurityPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: byte[] dataToSign = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce); clientSignature = new SignatureData { Signature = this.LocalPrivateKey.SignData(dataToSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1), Algorithm = RsaSha1Signature, }; break; case SecurityPolicyUris.Basic256Sha256: byte[] dataToSign256 = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce); clientSignature = new SignatureData { Signature = this.LocalPrivateKey.SignData(dataToSign256, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1), Algorithm = RsaSha256Signature, }; break; default: clientSignature = new SignatureData(); break; } // supported UserIdentityToken types are AnonymousIdentityToken, UserNameIdentityToken, IssuedIdentityToken, X509IdentityToken UserIdentityToken identityToken = null; SignatureData tokenSignature = null; // if UserIdentity type is IssuedIdentity if (this.UserIdentity is IssuedIdentity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.IssuedToken); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var issuedIdentity = (IssuedIdentity)this.UserIdentity; byte[] plainText = Concat(issuedIdentity.TokenData, this.RemoteNonce); var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; RSA asymRemoteEncryptionKey; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey(); identityToken = new IssuedIdentityToken { TokenData = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri), EncryptionAlgorithm = RsaV15KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Basic256: case SecurityPolicyUris.Basic256Sha256: asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey(); identityToken = new IssuedIdentityToken { TokenData = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri), EncryptionAlgorithm = RsaOaepKeyWrap, PolicyId = tokenPolicy.PolicyId }; break; default: identityToken = new IssuedIdentityToken { TokenData = issuedIdentity.TokenData, EncryptionAlgorithm = null, PolicyId = tokenPolicy.PolicyId }; break; } tokenSignature = new SignatureData(); } // if UserIdentity type is X509Identity else if (this.UserIdentity is X509Identity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Certificate); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var x509Identity = (X509Identity)this.UserIdentity; identityToken = new X509IdentityToken { CertificateData = x509Identity.Certificate?.RawData, PolicyId = tokenPolicy.PolicyId }; var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: var asymSigningKey = x509Identity.Certificate?.GetRSAPrivateKey(); if (asymSigningKey != null) { byte[] dataToSign = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce); tokenSignature = new SignatureData { Signature = asymSigningKey.SignData(dataToSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1), Algorithm = RsaSha1Signature, }; break; } tokenSignature = new SignatureData(); break; case SecurityPolicyUris.Basic256Sha256: var asymSigningKey256 = x509Identity.Certificate?.GetRSAPrivateKey(); if (asymSigningKey256 != null) { byte[] dataToSign256 = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce); tokenSignature = new SignatureData { Signature = asymSigningKey256.SignData(dataToSign256, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1), Algorithm = RsaSha256Signature, }; break; } tokenSignature = new SignatureData(); break; default: tokenSignature = new SignatureData(); break; } } // if UserIdentity type is UserNameIdentity else if (this.UserIdentity is UserNameIdentity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.UserName); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var userNameIdentity = (UserNameIdentity)this.UserIdentity; byte[] plainText = Concat(System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password), this.RemoteNonce); var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; RSA asymRemoteEncryptionKey; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey(); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri), EncryptionAlgorithm = RsaV15KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Basic256: case SecurityPolicyUris.Basic256Sha256: asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey(); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri), EncryptionAlgorithm = RsaOaepKeyWrap, PolicyId = tokenPolicy.PolicyId }; break; default: identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password), EncryptionAlgorithm = null, PolicyId = tokenPolicy.PolicyId }; break; } tokenSignature = new SignatureData(); } // if UserIdentity type is AnonymousIdentity or null else { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } identityToken = new AnonymousIdentityToken { PolicyId = tokenPolicy.PolicyId }; tokenSignature = new SignatureData(); } var activateSessionRequest = new ActivateSessionRequest { ClientSignature = clientSignature, LocaleIds = new[] { CultureInfo.CurrentUICulture.TwoLetterISOLanguageName }, UserIdentityToken = identityToken, UserTokenSignature = tokenSignature }; var activateSessionResponse = await this.ActivateSessionAsync(activateSessionRequest).ConfigureAwait(false); this.RemoteNonce = activateSessionResponse.ServerNonce; // fetch namespace array, etc. var readValueIds = new ReadValueId[] { new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_NamespaceArray), AttributeId = AttributeIds.Value }, new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_ServerArray), AttributeId = AttributeIds.Value } }; var readRequest = new ReadRequest { NodesToRead = readValueIds }; var readResponse = await this.ReadAsync(readRequest).ConfigureAwait(false); if (readResponse.Results.Length == 2) { if (StatusCode.IsGood(readResponse.Results[0].StatusCode)) { this.NamespaceUris.Clear(); this.NamespaceUris.AddRange(readResponse.Results[0].GetValueOrDefault <string[]>()); } if (StatusCode.IsGood(readResponse.Results[1].StatusCode)) { this.ServerUris.Clear(); this.ServerUris.AddRange(readResponse.Results[1].GetValueOrDefault <string[]>()); } } }
private void OkBTN_Click(object sender, EventArgs e) { try { // check that discover has completed. if (!m_discoverySucceeded) { DialogResult result = MessageBox.Show( "Endpoint information may be out of date because the discovery process has not completed. Continue anyways?", this.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result != DialogResult.Yes) { return; } } EndpointConfiguration configuration = m_endpointConfiguration; if (configuration == null) { configuration = EndpointConfiguration.Create(m_configuration); } if (m_currentDescription == null) { m_currentDescription = CreateDescriptionFromSelections(); } // the discovery endpoint should always be on the same machine as the server. // if there is a mismatch it is likely because the server has multiple addresses // and was not configured to return the current address to the client. // The code automatically updates the domain in the url. Uri endpointUrl = Utils.ParseUri(m_currentDescription.EndpointUrl); if (m_discoverySucceeded) { if (!Utils.AreDomainsEqual(endpointUrl, m_discoveryUrl)) { UriBuilder url = new UriBuilder(endpointUrl); url.Host = m_discoveryUrl.DnsSafeHost; if (url.Scheme == m_discoveryUrl.Scheme) { url.Port = m_discoveryUrl.Port; } endpointUrl = url.Uri; m_currentDescription.EndpointUrl = endpointUrl.ToString(); } } // set the encoding. Encoding encoding = (Encoding)EncodingCB.SelectedItem; configuration.UseBinaryEncoding = encoding != Encoding.Xml; if (m_endpoint == null) { m_endpoint = new ConfiguredEndpoint(null, m_currentDescription, configuration); } else { m_endpoint.Update(m_currentDescription); m_endpoint.Update(configuration); } // set the user token policy. m_endpoint.SelectedUserTokenPolicyIndex = FindBestUserTokenPolicy(m_currentDescription); // update the user identity. UserTokenType userTokenType = (UserTokenType)UserTokenTypeCB.SelectedItem; UserIdentityToken userIdentity = null; if (!m_userIdentities.TryGetValue(userTokenType, out userIdentity)) { userIdentity = null; } m_endpoint.UserIdentity = userIdentity; DialogResult = DialogResult.OK; } catch (Exception exception) { GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception); } }
public async Task UserIdentityToken_NullToken() { var token = await UserIdentityToken.ParseAsync(null, Guid.NewGuid()); }
/// <summary> /// Activates the session and binds it to the current secure channel. /// </summary> public bool Activate( OperationContext context, List <SoftwareCertificate> clientSoftwareCertificates, UserIdentityToken identityToken, IUserIdentity identity, IUserIdentity effectiveIdentity, StringCollection localeIds, byte[] serverNonce) { lock (m_lock) { // update user identity. bool changed = false; if (identityToken != null) { if (UpdateUserIdentity(identityToken, identity, effectiveIdentity)) { changed = true; } } // update local ids. if (UpdateLocaleIds(localeIds)) { changed = true; } if (!m_activated) { // toggle the activated flag. m_activated = true; // save the software certificates. m_softwareCertificates = clientSoftwareCertificates; TraceState("FIRST ACTIVATION"); } else { // bind to the new secure channel. m_secureChannelId = context.ChannelContext.SecureChannelId; TraceState("RE-ACTIVATION"); } // update server nonce. m_serverNonce = serverNonce; // build list of signed certificates for audit event. List <SignedSoftwareCertificate> signedSoftwareCertificates = new List <SignedSoftwareCertificate>(); if (clientSoftwareCertificates != null) { foreach (SoftwareCertificate softwareCertificate in clientSoftwareCertificates) { SignedSoftwareCertificate item = new SignedSoftwareCertificate(); item.CertificateData = softwareCertificate.SignedCertificate.GetRawCertData(); signedSoftwareCertificates.Add(item); } } // raise an audit event. ServerSystemContext systemContext = m_server.DefaultSystemContext.Copy(context); ReportAuditActivateSessionEvent(systemContext); // update the contact time. lock (m_diagnostics) { m_diagnostics.ClientLastContactTime = DateTime.UtcNow; } // indicate whether the user context has changed. return(changed); } }
/// <inheritdoc/> protected override async Task OnOpenAsync(CancellationToken token = default(CancellationToken)) { this.logger?.LogInformation($"Opening session channel with endpoint '{this.RemoteEndpoint.EndpointUrl}'."); this.logger?.LogInformation($"SecurityPolicy: '{this.RemoteEndpoint.SecurityPolicyUri}'."); this.logger?.LogInformation($"SecurityMode: '{this.RemoteEndpoint.SecurityMode}'."); this.logger?.LogInformation($"UserIdentity: '{this.UserIdentity}'."); await base.OnOpenAsync(token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); // if SessionId is provided then we skip the CreateSessionRequest and go directly to (re)ActivateSession. // requires from previous Session: SessionId, AuthenticationToken, RemoteNonce if (this.SessionId == null) { var localNonce = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.GetNextNonce(NonceLength) : null; var localCertificate = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.LocalCertificate : null; var createSessionRequest = new CreateSessionRequest { ClientDescription = this.LocalDescription, EndpointUrl = this.RemoteEndpoint.EndpointUrl, SessionName = this.LocalDescription.ApplicationName, ClientNonce = localNonce, ClientCertificate = localCertificate, RequestedSessionTimeout = this.options.SessionTimeout, MaxResponseMessageSize = this.RemoteMaxMessageSize }; var createSessionResponse = await this.CreateSessionAsync(createSessionRequest).ConfigureAwait(false); this.SessionId = createSessionResponse.SessionId; this.AuthenticationToken = createSessionResponse.AuthenticationToken; this.RemoteNonce = createSessionResponse.ServerNonce; // verify the server's certificate is the same as the certificate from the selected endpoint. if (this.RemoteEndpoint.ServerCertificate != null && !this.RemoteEndpoint.ServerCertificate.SequenceEqual(createSessionResponse.ServerCertificate)) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Server did not return the same certificate used to create the channel."); } // verify the server's signature. ISigner verifier = null; bool verified = false; switch (this.RemoteEndpoint.SecurityPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: verifier = SignerUtilities.GetSigner("SHA-1withRSA"); verifier.Init(false, this.RemotePublicKey); verifier.BlockUpdate(localCertificate, 0, localCertificate.Length); verifier.BlockUpdate(localNonce, 0, localNonce.Length); verified = verifier.VerifySignature(createSessionResponse.ServerSignature.Signature); break; case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: verifier = SignerUtilities.GetSigner("SHA-256withRSA"); verifier.Init(false, this.RemotePublicKey); verifier.BlockUpdate(localCertificate, 0, localCertificate.Length); verifier.BlockUpdate(localNonce, 0, localNonce.Length); verified = verifier.VerifySignature(createSessionResponse.ServerSignature.Signature); break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: verifier = SignerUtilities.GetSigner("SHA-256withRSAandMGF1"); verifier.Init(false, this.RemotePublicKey); verifier.BlockUpdate(localCertificate, 0, localCertificate.Length); verifier.BlockUpdate(localNonce, 0, localNonce.Length); verified = verifier.VerifySignature(createSessionResponse.ServerSignature.Signature); break; default: verified = true; break; } verifier = null; if (!verified) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client."); } } // create client signature SignatureData clientSignature = null; ISigner signer = null; switch (this.RemoteEndpoint.SecurityPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: signer = SignerUtilities.GetSigner("SHA-1withRSA"); signer.Init(true, this.LocalPrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); clientSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha1Signature, }; break; case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: signer = SignerUtilities.GetSigner("SHA-256withRSA"); signer.Init(true, this.LocalPrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); clientSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha256Signature, }; break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: signer = SignerUtilities.GetSigner("SHA-256withRSAandMGF1"); signer.Init(true, this.LocalPrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); clientSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaPssSha256Signature, }; break; default: clientSignature = new SignatureData(); break; } signer = null; // supported UserIdentityToken types are AnonymousIdentityToken, UserNameIdentityToken, IssuedIdentityToken, X509IdentityToken UserIdentityToken identityToken = null; SignatureData tokenSignature = null; // if UserIdentity type is IssuedIdentity if (this.UserIdentity is IssuedIdentity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.IssuedToken); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var issuedIdentity = (IssuedIdentity)this.UserIdentity; int plainTextLength = issuedIdentity.TokenData.Length + this.RemoteNonce.Length; IBufferedCipher encryptor; byte[] cipherText; int pos; var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: encryptor = CipherUtilities.GetCipher("RSA//PKCS1Padding"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(issuedIdentity.TokenData, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new IssuedIdentityToken { TokenData = cipherText, EncryptionAlgorithm = RsaV15KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Basic256: case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: encryptor = CipherUtilities.GetCipher("RSA//OAEPPADDING"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(issuedIdentity.TokenData, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new IssuedIdentityToken { TokenData = cipherText, EncryptionAlgorithm = RsaOaepKeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: encryptor = CipherUtilities.GetCipher("RSA//OAEPWITHSHA256ANDMGF1PADDING"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(issuedIdentity.TokenData, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new IssuedIdentityToken { TokenData = cipherText, EncryptionAlgorithm = RsaOaepSha256KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; default: identityToken = new IssuedIdentityToken { TokenData = issuedIdentity.TokenData, EncryptionAlgorithm = null, PolicyId = tokenPolicy.PolicyId }; break; } tokenSignature = new SignatureData(); encryptor = null; cipherText = null; } // if UserIdentity type is X509Identity else if (this.UserIdentity is X509Identity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Certificate); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var x509Identity = (X509Identity)this.UserIdentity; identityToken = new X509IdentityToken { CertificateData = x509Identity.Certificate?.GetEncoded(), PolicyId = tokenPolicy.PolicyId }; var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: signer = SignerUtilities.GetSigner("SHA-1withRSA"); signer.Init(true, x509Identity.PrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); tokenSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha1Signature, }; break; case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: signer = SignerUtilities.GetSigner("SHA-256withRSA"); signer.Init(true, x509Identity.PrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); tokenSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha256Signature, }; break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: signer = SignerUtilities.GetSigner("SHA-256withRSAandMGF1"); signer.Init(true, x509Identity.PrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); tokenSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha256Signature, }; break; default: tokenSignature = new SignatureData(); break; } signer = null; } // if UserIdentity type is UserNameIdentity else if (this.UserIdentity is UserNameIdentity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.UserName); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var userNameIdentity = (UserNameIdentity)this.UserIdentity; byte[] passwordBytes = userNameIdentity.Password != null?System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password) : new byte[0]; int plainTextLength = passwordBytes.Length + this.RemoteNonce.Length; IBufferedCipher encryptor; byte[] cipherText; int pos; var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: encryptor = CipherUtilities.GetCipher("RSA//PKCS1Padding"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(passwordBytes, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = cipherText, EncryptionAlgorithm = RsaV15KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Basic256: case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: encryptor = CipherUtilities.GetCipher("RSA//OAEPPADDING"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(passwordBytes, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = cipherText, EncryptionAlgorithm = RsaOaepKeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: encryptor = CipherUtilities.GetCipher("RSA//OAEPWITHSHA256ANDMGF1PADDING"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(passwordBytes, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = cipherText, EncryptionAlgorithm = RsaOaepSha256KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; default: identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = passwordBytes, EncryptionAlgorithm = null, PolicyId = tokenPolicy.PolicyId }; break; } tokenSignature = new SignatureData(); passwordBytes = null; encryptor = null; cipherText = null; } // if UserIdentity type is AnonymousIdentity or null else { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } identityToken = new AnonymousIdentityToken { PolicyId = tokenPolicy.PolicyId }; tokenSignature = new SignatureData(); } var activateSessionRequest = new ActivateSessionRequest { ClientSignature = clientSignature, LocaleIds = new[] { CultureInfo.CurrentUICulture.TwoLetterISOLanguageName }, UserIdentityToken = identityToken, UserTokenSignature = tokenSignature }; var activateSessionResponse = await this.ActivateSessionAsync(activateSessionRequest).ConfigureAwait(false); this.RemoteNonce = activateSessionResponse.ServerNonce; // fetch namespace array, etc. var readValueIds = new ReadValueId[] { new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_NamespaceArray), AttributeId = AttributeIds.Value }, new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_ServerArray), AttributeId = AttributeIds.Value } }; var readRequest = new ReadRequest { NodesToRead = readValueIds }; var readResponse = await this.ReadAsync(readRequest).ConfigureAwait(false); if (readResponse.Results.Length == 2) { if (StatusCode.IsGood(readResponse.Results[0].StatusCode)) { this.NamespaceUris.Clear(); this.NamespaceUris.AddRange(readResponse.Results[0].GetValueOrDefault <string[]>()); } if (StatusCode.IsGood(readResponse.Results[1].StatusCode)) { this.ServerUris.Clear(); this.ServerUris.AddRange(readResponse.Results[1].GetValueOrDefault <string[]>()); } } // create the keep alive subscription. var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = DefaultPublishingInterval, RequestedMaxKeepAliveCount = DefaultKeepaliveCount, RequestedLifetimeCount = DefaultKeepaliveCount * 3, PublishingEnabled = true, }; var subscriptionResponse = await this.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); // link up the dataflow blocks var id = subscriptionResponse.SubscriptionId; var linkToken = this.LinkTo(this.actionBlock, pr => pr.SubscriptionId == id); // start publishing. this.stateMachineTask = Task.Run(() => this.StateMachineAsync(this.stateMachineCts.Token)); }
/// <summary> /// Validates the identity token supplied by the client. /// </summary> private UserIdentityToken ValidateUserIdentityToken( ExtensionObject identityToken, SignatureData userTokenSignature, out UserTokenPolicy policy) { policy = null; // check for empty token. if (identityToken == null || identityToken.Body == null) { // not changing the token if already activated. if (m_activated) { return(null); } // check if an anonymous login is permitted. if (m_endpoint.UserIdentityTokens != null && m_endpoint.UserIdentityTokens.Count > 0) { bool found = false; for (int ii = 0; ii < m_endpoint.UserIdentityTokens.Count; ii++) { if (m_endpoint.UserIdentityTokens[ii].TokenType == UserTokenType.Anonymous) { found = true; policy = m_endpoint.UserIdentityTokens[ii]; break; } } if (!found) { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Anonymous user token policy not supported."); } } // create an anonymous token to use for subsequent validation. AnonymousIdentityToken anonymousToken = new AnonymousIdentityToken(); anonymousToken.PolicyId = policy.PolicyId; return(anonymousToken); } UserIdentityToken token = null; // check for unrecognized token. if (!typeof(UserIdentityToken).IsInstanceOfType(identityToken.Body)) { //handle the use case when the UserIdentityToken is binary encoded over xml message encoding if (identityToken.Encoding == ExtensionObjectEncoding.Binary && typeof(byte[]).IsInstanceOfType(identityToken.Body)) { UserIdentityToken newToken = BaseVariableState.DecodeExtensionObject(null, typeof(UserIdentityToken), identityToken, false) as UserIdentityToken; if (newToken == null) { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Invalid user identity token provided."); } policy = m_endpoint.FindUserTokenPolicy(newToken.PolicyId); if (policy == null) { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "User token policy not supported.", "Opc.Ua.Server.Session.ValidateUserIdentityToken"); } switch (policy.TokenType) { case UserTokenType.Anonymous: token = BaseVariableState.DecodeExtensionObject(null, typeof(AnonymousIdentityToken), identityToken, true) as AnonymousIdentityToken; break; case UserTokenType.UserName: token = BaseVariableState.DecodeExtensionObject(null, typeof(UserNameIdentityToken), identityToken, true) as UserNameIdentityToken; break; case UserTokenType.Certificate: token = BaseVariableState.DecodeExtensionObject(null, typeof(X509IdentityToken), identityToken, true) as X509IdentityToken; break; case UserTokenType.IssuedToken: token = BaseVariableState.DecodeExtensionObject(null, typeof(IssuedIdentityToken), identityToken, true) as IssuedIdentityToken; break; default: throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Invalid user identity token provided."); } } else { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Invalid user identity token provided."); } } else { // get the token. token = (UserIdentityToken)identityToken.Body; } // find the user token policy. policy = m_endpoint.FindUserTokenPolicy(token.PolicyId); if (policy == null) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, "User token policy not supported."); } // determine the security policy uri. string securityPolicyUri = policy.SecurityPolicyUri; if (String.IsNullOrEmpty(securityPolicyUri)) { securityPolicyUri = m_endpoint.SecurityPolicyUri; } if (ServerBase.RequireEncryption(m_endpoint)) { // decrypt the token. if (m_serverCertificate == null) { m_serverCertificate = CertificateFactory.Create(m_endpoint.ServerCertificate, true); // check for valid certificate. if (m_serverCertificate == null) { throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationCertificate cannot be found."); } } try { token.Decrypt(m_serverCertificate, m_serverNonce, securityPolicyUri); } catch (Exception e) { if (e is ServiceResultException) { throw; } throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, e, "Could not decrypt identity token."); } // verify the signature. if (securityPolicyUri != SecurityPolicies.None) { byte[] dataToSign = Utils.Append(m_serverCertificate.RawData, m_serverNonce); if (!token.Verify(dataToSign, userTokenSignature, securityPolicyUri)) { throw new ServiceResultException(StatusCodes.BadUserSignatureInvalid, "Invalid user signature!"); } } } // validate user identity token. return(token); }
public async Task UserIdentityToken_WhitespaceToken() { var token = await UserIdentityToken.ParseAsync(string.Empty, Guid.NewGuid()); }
/// <summary> /// Create and Activate a session without security. /// </summary> /// <remarks> /// The request header is used to call services directly, /// without establishing a session with a client. /// </remarks> /// <param name="server">The server to connect to.</param> /// <param name="sessionName">A session name.</param> /// <returns>The request header for the session.</returns> public static RequestHeader CreateAndActivateSession( this SessionServerBase server, string sessionName, bool useSecurity = false, UserIdentityToken identityToken = null, double sessionTimeout = DefaultSessionTimeout, uint maxResponseMessageSize = DefaultMaxResponseMessageSize) { // Find TCP endpoint var endpoints = server.GetEndpoints(); var endpoint = endpoints.FirstOrDefault(e => e.TransportProfileUri.Equals(Profiles.UaTcpTransport, StringComparison.Ordinal) || e.TransportProfileUri.Equals(Profiles.HttpsBinaryTransport, StringComparison.Ordinal)); if (endpoint == null) { throw new Exception("Unsupported transport profile."); } // fake profiles if (useSecurity) { endpoint.SecurityMode = MessageSecurityMode.Sign; endpoint.SecurityPolicyUri = SecurityPolicies.Basic256Sha256; } else { endpoint.SecurityMode = MessageSecurityMode.None; endpoint.SecurityPolicyUri = SecurityPolicies.None; } var context = new SecureChannelContext( sessionName, endpoint, RequestEncoding.Binary); // set security context SecureChannelContext.Current = context; var requestHeader = new RequestHeader(); // Create session var response = server.CreateSession( requestHeader, null, null, null, sessionName, null, null, sessionTimeout, maxResponseMessageSize, out var sessionId, out var authenticationToken, out sessionTimeout, out var serverNonce, out var serverCertificate, out var endpointDescriptions, out var serverSoftwareCertificates, out var signatureData, out var maxRequestMessageSize); ValidateResponse(response); // Activate session requestHeader.AuthenticationToken = authenticationToken; response = server.ActivateSession(requestHeader, signatureData, new SignedSoftwareCertificateCollection(), new StringCollection(), (identityToken != null) ? new ExtensionObject(identityToken) : null, null, out serverNonce, out var results, out var diagnosticInfos); ValidateResponse(response); return(requestHeader); }
/// <summary> /// Creates a new instance. /// </summary> public ImpersonateEventArgs(UserIdentityToken newIdentity, UserTokenPolicy userTokenPolicy) { m_newIdentity = newIdentity; m_userTokenPolicy = userTokenPolicy; }
/// <summary> /// Validates the identity token supplied by the client. /// </summary> /// <param name="identityToken"></param> /// <param name="userTokenSignature"></param> /// <returns></returns> private bool ValidateUserIdentityToken(ExtensionObject identityToken, SignatureData userTokenSignature) { UserIdentityToken token = null; UserTokenPolicy policy; if (identityToken == null || identityToken.Body == null) { if (_activated) { // not changing the token if already activated. return(false); } policy = Endpoint.UserIdentityTokens? .FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous); if (policy == null) { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Anonymous user token policy not supported."); } // create an anonymous token to use for subsequent validation. token = new AnonymousIdentityToken { PolicyId = policy.PolicyId }; } else if (!typeof(UserIdentityToken).IsInstanceOfType(identityToken.Body)) { // Decode identity token from binary. token = DecodeUserIdentityToken(identityToken, out policy); } else { token = (UserIdentityToken)identityToken.Body; // find the user token policy. policy = Endpoint.FindUserTokenPolicy(token.PolicyId); if (policy == null) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, "User token policy not supported."); } } // determine the security policy uri. var securityPolicyUri = policy.SecurityPolicyUri; if (string.IsNullOrEmpty(securityPolicyUri)) { securityPolicyUri = Endpoint.SecurityPolicyUri; } if (securityPolicyUri != SecurityPolicies.None) { // decrypt the user identity token. if (_serverCertificate == null) { _serverCertificate = CertificateFactory.Create( Endpoint.ServerCertificate, true); // check for valid certificate. if (_serverCertificate == null) { throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationCertificate cannot be found."); } } try { token.Decrypt(_serverCertificate, _serverNonce, securityPolicyUri); } catch (ServiceResultException) { throw; } catch (Exception e) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, e, "Could not decrypt identity token."); } // ... and verify the signature if any. VerifyUserTokenSignature(userTokenSignature, token, securityPolicyUri); } // We have a valid token - validate it through the handler chain. var arg = new UserIdentityHandlerArgs { CurrentIdentities = Identities, Token = token }; _validator?.Invoke(this, arg); if (arg.ValidationException != null) { throw arg.ValidationException; } if (arg.NewIdentities != null) { Identities = arg.NewIdentities; return(true); } return(false); // No new identities }
public async Task UserIdentityToken_MalformedToken() { var token = await UserIdentityToken.ParseAsync("malformed_token", Guid.NewGuid()); }
internal static void AddUserToken(UserIdentityToken usertoken) { Add(SessionKeys.UserToken, usertoken); }