/// <summary>
            /// Activates the session and binds it to the current secure channel.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="clientSignature"></param>
            /// <param name="clientSoftwareCertificates"></param>
            /// <param name="userIdentityToken"></param>
            /// <param name="userTokenSignature"></param>
            /// <param name="serverNonce"></param>
            /// <returns></returns>
            internal bool Activate(RequestContextModel context, SignatureData clientSignature,
                                   List <SoftwareCertificate> clientSoftwareCertificates, ExtensionObject userIdentityToken,
                                   SignatureData userTokenSignature, byte[] serverNonce)
            {
                lock (_lock) {
                    var changed = ValidateActivation(context, clientSignature, clientSoftwareCertificates,
                                                     userIdentityToken, userTokenSignature);
                    if (!_activated)
                    {
                        _activated = true;
                    }
                    else
                    {
                        // Reactivation = bind to the new secure channel.
                        _secureChannelId = context.ChannelContext.SecureChannelId;
                    }

                    // update server nonce.
                    _serverNonce = serverNonce;
                    // build list of signed certificates for audit event.
                    var signedSoftwareCertificates = new List <SignedSoftwareCertificate>();
                    if (clientSoftwareCertificates != null)
                    {
                        foreach (var softwareCertificate in clientSoftwareCertificates)
                        {
                            var item = new SignedSoftwareCertificate {
                                CertificateData = softwareCertificate.SignedCertificate.RawData
                            };
                            signedSoftwareCertificates.Add(item);
                        }
                    }
                    _timeoutTimer.Change(_timeout, Timeout.InfiniteTimeSpan);
                    return(changed);
                }
            }
            /// <summary>
            /// Create session
            /// </summary>
            /// <param name="manager"></param>
            /// <param name="context"></param>
            /// <param name="id"></param>
            /// <param name="endpoint"></param>
            /// <param name="serverCertificate"></param>
            /// <param name="clientNonce"></param>
            /// <param name="timeout"></param>
            /// <param name="serverNonce"></param>
            /// <param name="clientCertificate"></param>
            /// <param name="maxRequestAge"></param>
            /// <param name="validator"></param>
            public GatewaySession(SessionServices manager,
                                  RequestContextModel context, NodeId id, EndpointDescription endpoint,
                                  X509Certificate2 clientCertificate, byte[] clientNonce,
                                  X509Certificate2 serverCertificate, byte[] serverNonce,
                                  TimeSpan timeout, TimeSpan maxRequestAge, UserIdentityHandler validator)
            {
                if (context == null)
                {
                    throw new ArgumentNullException(nameof(context));
                }
                if (context.ChannelContext == null)
                {
                    throw new ServiceResultException(StatusCodes.BadSecureChannelIdInvalid);
                }
                _validator         = validator;
                _secureChannelId   = context.ChannelContext.SecureChannelId;
                _serverNonce       = serverNonce;
                _serverCertificate = serverCertificate;
                _clientCertificate = clientCertificate;
                _maxRequestAge     = maxRequestAge;
                Endpoint           = endpoint;
                Identities         = new List <IUserIdentity>();

                Id             = id;
                ClientNonce    = clientNonce;
                MessageContext = new ServiceMessageContext();

                _cts          = new CancellationTokenSource();
                _timeout      = timeout;
                _timeoutTimer = new Timer(o => OnTimeout(manager), null,
                                          timeout, Timeout.InfiniteTimeSpan);
            }
Exemplo n.º 3
0
 /// <summary>
 /// Called when a new request arrives.
 /// </summary>
 /// <param name="context"></param>
 public void RequestReceived(RequestContextModel context)
 {
     if (context == null)
     {
         throw new ArgumentNullException(nameof(context));
     }
     _requests.TryAdd(context.RequestId, context);
 }
Exemplo n.º 4
0
        /// <summary>
        /// Called when a request completes (normally or abnormally).
        /// </summary>
        public void RequestCompleted(RequestContextModel context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // remove the request.
            _requests.TryRemove(context.RequestId, out context);
        }
            /// <summary>
            /// Validate before activation
            /// </summary>
            /// <param name="context"></param>
            /// <param name="clientSignature"></param>
            /// <param name="clientSoftwareCertificates"></param>
            /// <param name="userIdentityToken"></param>
            /// <param name="userTokenSignature"></param>
            /// <returns></returns>
            private bool ValidateActivation(RequestContextModel context, SignatureData clientSignature,
                                            List <SoftwareCertificate> clientSoftwareCertificates, ExtensionObject userIdentityToken,
                                            SignatureData userTokenSignature)
            {
                // 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.
                var endpoint = context.ChannelContext.EndpointDescription;

                if (endpoint.SecurityPolicyUri != Endpoint.SecurityPolicyUri ||
                    endpoint.SecurityMode != Endpoint.SecurityMode)
                {
                    throw new ServiceResultException(StatusCodes.BadSecurityPolicyRejected);
                }

                // verify the client signature.
                if (_clientCertificate != null)
                {
                    VerifyClientSignature(clientSignature);
                }

                if (!_activated)
                {
                    // must active the session on the channel that was used to create it.
                    if (_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.
                return(ValidateUserIdentityToken(userIdentityToken, userTokenSignature));
            }
        /// <inheritdoc/>
        public virtual bool ActivateSession(RequestContextModel context,
                                            NodeId authenticationToken, SignatureData clientSignature,
                                            List <SoftwareCertificate> clientSoftwareCertificates,
                                            ExtensionObject userIdentityToken, SignatureData userTokenSignature,
                                            StringCollection localeIds, out byte[] serverNonce)
        {
            // find session.
            GatewaySession session = null;

            lock (_lock) {
                if (!_sessions.TryGetValue(authenticationToken, out session))
                {
                    throw new ServiceResultException(StatusCodes.BadSessionClosed);
                }
            }

            if (session.IsClosed)
            {
                throw new ServiceResultException(StatusCodes.BadSessionClosed);
            }

            // Activate session.
            var nonceLength = (uint)_configuration.NonceLength;

            serverNonce = Utils.Nonce.CreateNonce(nonceLength);
            var contextChanged = session.Activate(context, clientSignature,
                                                  clientSoftwareCertificates, userIdentityToken, userTokenSignature,
                                                  serverNonce);

            if (contextChanged)
            {
                _sessionActivated?.Invoke(session, null);
            }

            // indicates that the identity context for the session has changed.
            return(contextChanged);
        }
        /// <inheritdoc/>
        public IServerSession CreateSession(RequestContextModel context,
                                            EndpointDescription endpoint, X509Certificate2 serverCertificate,
                                            byte[] clientNonce, X509Certificate2 clientCertificate, double requestedTimeout,
                                            out NodeId sessionId, out NodeId authenticationToken,
                                            out byte[] serverNonce, out double revisedTimeout)
        {
            GatewaySession session = null;

            lock (_lock) {
                // check session count.
                if (_configuration.MaxSessionCount > 0 &&
                    _sessions.Count >= _configuration.MaxSessionCount)
                {
                    throw new ServiceResultException(StatusCodes.BadTooManySessions);
                }

                // check for same Nonce in another session
                if (clientNonce != null)
                {
                    foreach (var sessionIterator in _sessions.Values)
                    {
                        if (Utils.CompareNonce(sessionIterator.ClientNonce, clientNonce))
                        {
                            throw new ServiceResultException(StatusCodes.BadNonceInvalid);
                        }
                    }
                }

                // Create session
                sessionId           = new NodeId(Guid.NewGuid());
                authenticationToken = new NodeId(Utils.Nonce.CreateNonce(kDefaultNonceLength));
                var nonceLength = (uint)_configuration.NonceLength;
                serverNonce = Utils.Nonce.CreateNonce(nonceLength == 0 ? kDefaultNonceLength :
                                                      nonceLength);

                var maxSessionTimeout = _configuration.MaxSessionTimeout.TotalMilliseconds;
                var minSessionTimeout = _configuration.MinSessionTimeout.TotalMilliseconds;
                if (requestedTimeout > maxSessionTimeout)
                {
                    revisedTimeout = maxSessionTimeout;
                }
                else if (requestedTimeout < minSessionTimeout)
                {
                    revisedTimeout = minSessionTimeout;
                }
                else
                {
                    revisedTimeout = requestedTimeout;
                }

                // Add session to list
                session = new GatewaySession(this, context, sessionId, endpoint,
                                             clientCertificate, clientNonce, serverCertificate, serverNonce,
                                             TimeSpan.FromMilliseconds(revisedTimeout), _configuration.MaxRequestAge,
                                             _validateUser);
                if (!_sessions.TryAdd(authenticationToken, session))
                {
                    throw new ServiceResultException(StatusCodes.BadInternalError);
                }
            }

            _sessionCreated?.Invoke(session, null);
            return(session);
        }