public override ResponseHeader CreateSession(
RequestHeader requestHeader,
ApplicationDescription clientDescription,
string serverUri,
string endpointUrl,
string sessionName,
byte[] clientNonce,
byte[] clientCertificate,
double requestedSessionTimeout,
uint maxResponseMessageSize,
out NodeId sessionId,
out NodeId authenticationToken,
out double revisedSessionTimeout,
out byte[] serverNonce,
out byte[] serverCertificate,
out EndpointDescriptionCollection serverEndpoints,
out SignedSoftwareCertificateCollection serverSoftwareCertificates,
out SignatureData serverSignature,
out uint maxRequestMessageSize)
{
sessionId = 0;
revisedSessionTimeout = 0;
serverNonce = null;
serverCertificate = null;
serverSoftwareCertificates = null;
serverSignature = null;
maxRequestMessageSize = (uint)MessageContext.MaxMessageSize;
OperationContext context = ValidateRequest(requestHeader, RequestType.CreateSession);
try
{
// check the server uri.
if (!String.IsNullOrEmpty(serverUri))
{
if (serverUri != this.Configuration.ApplicationUri)
{
throw new ServiceResultException(StatusCodes.BadServerUriInvalid);
}
}
bool requireEncryption = ServerBase.RequireEncryption(context.ChannelContext.EndpointDescription);
if (!requireEncryption && clientCertificate != null)
{
requireEncryption = true;
}
// validate client application instance certificate.
X509Certificate2 parsedClientCertificate = null;
if (requireEncryption && clientCertificate != null && clientCertificate.Length > 0)
{
try
{
parsedClientCertificate = CertificateFactory.Create(clientCertificate, true);
if (context.SecurityPolicyUri != SecurityPolicies.None)
{
string certificateApplicationUri = Utils.GetApplicationUriFromCertficate(parsedClientCertificate);
// verify if applicationUri from ApplicationDescription matches the applicationUri in the client certificate.
if (!String.IsNullOrEmpty(certificateApplicationUri) &&
!String.IsNullOrEmpty(clientDescription.ApplicationUri) &&
certificateApplicationUri != clientDescription.ApplicationUri)
{
throw ServiceResultException.Create(
StatusCodes.BadCertificateUriInvalid,
"The URI specified in the ApplicationDescription does not match the URI in the Certificate.");
}
CertificateValidator.Validate(parsedClientCertificate);
/*X509Certificate2Collection clientCertificateChain = Utils.ParseCertificateChainBlob(clientCertificate);
CertificateValidator.Validate(clientCertificateChain);
parsedClientCertificate = clientCertificateChain[0];*/
}
}
catch (Exception e)
{
OnApplicationCertificateError(clientCertificate, new ServiceResult(e));
}
}
// verify the nonce provided by the client.
if (clientNonce != null)
{
if (clientNonce.Length < m_minNonceLength)
{
throw new ServiceResultException(StatusCodes.BadNonceInvalid);
}
}
// create the session.
Session session = ServerInternal.SessionManager.CreateSession(
context,
requireEncryption ? InstanceCertificate : null,
sessionName,
clientNonce,
clientDescription,
endpointUrl,
parsedClientCertificate,
requestedSessionTimeout,
maxResponseMessageSize,
out sessionId,
out authenticationToken,
out serverNonce,
out revisedSessionTimeout);
lock (m_lock)
{
// return the application instance certificate for the server.
if (requireEncryption)
{
serverCertificate = InstanceCertificate.RawData;
/*List<byte> certificateChainList = new List<byte>();
for (int i = 0; i < InstanceCertificateChain.Count; i++)
{
certificateChainList.AddRange(InstanceCertificateChain[i].RawData);
}
serverCertificate = certificateChainList.ToArray();*/
}
//session.ServerCertificateChain = serverCertificate;
// return the endpoints supported by the server.
serverEndpoints = GetEndpointDescriptions(endpointUrl, BaseAddresses, null);
// return the software certificates assigned to the server.
serverSoftwareCertificates = new SignedSoftwareCertificateCollection(ServerProperties.SoftwareCertificates);
// sign the nonce provided by the client.
serverSignature = null;
// sign the client nonce (if provided).
if (parsedClientCertificate != null && clientNonce != null)
{
byte[] dataToSign = Utils.Append(clientCertificate, clientNonce);
serverSignature = SecurityPolicies.Sign(InstanceCertificate, context.SecurityPolicyUri, dataToSign);
}
}
lock (ServerInternal.DiagnosticsLock)
{
ServerInternal.ServerDiagnostics.CurrentSessionCount++;
ServerInternal.ServerDiagnostics.CumulatedSessionCount++;
}
Utils.Trace("Server - SESSION CREATED. SessionId={0}", sessionId);
return CreateResponse(requestHeader, StatusCodes.Good);
}
catch (ServiceResultException e)
{
Utils.Trace("Server - SESSION CREATE failed. {0}", e.Message);
lock (ServerInternal.DiagnosticsLock)
{
ServerInternal.ServerDiagnostics.RejectedSessionCount++;
ServerInternal.ServerDiagnostics.RejectedRequestsCount++;
if (IsSecurityError(e.StatusCode))
{
ServerInternal.ServerDiagnostics.SecurityRejectedSessionCount++;
ServerInternal.ServerDiagnostics.SecurityRejectedRequestsCount++;
}
}
throw TranslateException((DiagnosticsMasks)requestHeader.ReturnDiagnostics, new StringCollection(), e);
}
finally
{
OnRequestComplete(context);
}
}