use of org.eclipse.milo.opcua.stack.core.types.structured.SignedSoftwareCertificate in project milo by eclipse.
the class SessionManager method activateSession.
private ActivateSessionResponse activateSession(ServiceRequest serviceRequest) throws UaException {
ActivateSessionRequest request = (ActivateSessionRequest) serviceRequest.getRequest();
long secureChannelId = serviceRequest.getSecureChannelId();
NodeId authToken = request.getRequestHeader().getAuthenticationToken();
List<SignedSoftwareCertificate> clientSoftwareCertificates = l(request.getClientSoftwareCertificates());
Session session = createdSessions.get(authToken);
if (session == null) {
session = activeSessions.get(authToken);
if (session == null) {
throw new UaException(StatusCodes.Bad_SessionIdInvalid);
} else {
verifyClientSignature(session, request);
SecurityConfiguration securityConfiguration = session.getSecurityConfiguration();
if (session.getSecureChannelId() == secureChannelId) {
/*
* Identity change
*/
UserIdentityToken identityToken = decodeIdentityToken(request.getUserIdentityToken(), session.getEndpoint().getUserIdentityTokens());
Object identityObject = validateIdentityToken(session, identityToken, request.getUserTokenSignature());
StatusCode[] results = new StatusCode[clientSoftwareCertificates.size()];
Arrays.fill(results, StatusCode.GOOD);
ByteString serverNonce = NonceUtil.generateNonce(32);
session.setClientAddress(serviceRequest.getClientAddress());
session.setIdentityObject(identityObject, identityToken);
session.setLastNonce(serverNonce);
session.setLocaleIds(request.getLocaleIds());
return new ActivateSessionResponse(serviceRequest.createResponseHeader(), serverNonce, results, new DiagnosticInfo[0]);
} else {
/*
* Associate session with new secure channel if client certificate and identity token match.
*/
ByteString clientCertificateBytes = serviceRequest.getClientCertificateBytes();
UserIdentityToken identityToken = decodeIdentityToken(request.getUserIdentityToken(), session.getEndpoint().getUserIdentityTokens());
Object identityObject = validateIdentityToken(session, identityToken, request.getUserTokenSignature());
boolean sameIdentity = Objects.equal(identityObject, session.getIdentityObject());
boolean sameCertificate = Objects.equal(clientCertificateBytes, securityConfiguration.getClientCertificateBytes());
if (sameIdentity && sameCertificate) {
SecurityConfiguration newSecurityConfiguration = createSecurityConfiguration(serviceRequest.getEndpoint(), clientCertificateBytes);
session.setEndpoint(serviceRequest.getEndpoint());
session.setSecureChannelId(secureChannelId);
session.setSecurityConfiguration(newSecurityConfiguration);
logger.debug("Session id={} is now associated with secureChannelId={}", session.getSessionId(), secureChannelId);
StatusCode[] results = new StatusCode[clientSoftwareCertificates.size()];
Arrays.fill(results, StatusCode.GOOD);
ByteString serverNonce = NonceUtil.generateNonce(32);
session.setClientAddress(serviceRequest.getClientAddress());
session.setLastNonce(serverNonce);
session.setLocaleIds(request.getLocaleIds());
return new ActivateSessionResponse(serviceRequest.createResponseHeader(), serverNonce, results, new DiagnosticInfo[0]);
} else {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed);
}
}
}
} else {
if (secureChannelId != session.getSecureChannelId()) {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed);
}
verifyClientSignature(session, request);
UserIdentityToken identityToken = decodeIdentityToken(request.getUserIdentityToken(), session.getEndpoint().getUserIdentityTokens());
Object identityObject = validateIdentityToken(session, identityToken, request.getUserTokenSignature());
createdSessions.remove(authToken);
activeSessions.put(authToken, session);
StatusCode[] results = new StatusCode[clientSoftwareCertificates.size()];
Arrays.fill(results, StatusCode.GOOD);
ByteString serverNonce = NonceUtil.generateNonce(32);
session.setClientAddress(serviceRequest.getClientAddress());
session.setIdentityObject(identityObject, identityToken);
session.setLocaleIds(request.getLocaleIds());
session.setLastNonce(serverNonce);
return new ActivateSessionResponse(serviceRequest.createResponseHeader(), serverNonce, results, new DiagnosticInfo[0]);
}
}
use of org.eclipse.milo.opcua.stack.core.types.structured.SignedSoftwareCertificate in project milo by eclipse.
the class SessionManager method createSession.
private CreateSessionResponse createSession(ServiceRequest serviceRequest) throws UaException {
CreateSessionRequest request = (CreateSessionRequest) serviceRequest.getRequest();
long maxSessionCount = server.getConfig().getLimits().getMaxSessionCount().longValue();
if (createdSessions.size() + activeSessions.size() >= maxSessionCount) {
throw new UaException(StatusCodes.Bad_TooManySessions);
}
ByteString serverNonce = NonceUtil.generateNonce(32);
NodeId authenticationToken = new NodeId(0, NonceUtil.generateNonce(32));
long maxRequestMessageSize = serviceRequest.getServer().getConfig().getEncodingLimits().getMaxMessageSize();
double revisedSessionTimeout = Math.max(5000, Math.min(server.getConfig().getLimits().getMaxSessionTimeout(), request.getRequestedSessionTimeout()));
ApplicationDescription clientDescription = request.getClientDescription();
long secureChannelId = serviceRequest.getSecureChannelId();
EndpointDescription endpoint = serviceRequest.getEndpoint();
SecurityPolicy securityPolicy = SecurityPolicy.fromUri(endpoint.getSecurityPolicyUri());
EndpointDescription[] serverEndpoints = server.getEndpointDescriptions().stream().filter(ed -> !ed.getEndpointUrl().endsWith("/discovery")).filter(ed -> endpointMatchesUrl(ed, request.getEndpointUrl())).filter(ed -> Objects.equal(endpoint.getTransportProfileUri(), ed.getTransportProfileUri())).map(SessionManager::stripNonEssentialFields).toArray(EndpointDescription[]::new);
if (serverEndpoints.length == 0) {
// GetEndpoints in UaStackServer returns *all* endpoints regardless of a hostname
// match in the endpoint URL if the result after filtering is 0 endpoints. Do the
// same here.
serverEndpoints = server.getEndpointDescriptions().stream().filter(ed -> !ed.getEndpointUrl().endsWith("/discovery")).filter(ed -> Objects.equal(endpoint.getTransportProfileUri(), ed.getTransportProfileUri())).map(SessionManager::stripNonEssentialFields).toArray(EndpointDescription[]::new);
}
ByteString clientNonce = request.getClientNonce();
if (securityPolicy != SecurityPolicy.None) {
NonceUtil.validateNonce(clientNonce);
if (clientNonces.contains(clientNonce)) {
throw new UaException(StatusCodes.Bad_NonceInvalid);
}
}
if (securityPolicy != SecurityPolicy.None && clientNonce.isNotNull()) {
clientNonces.add(clientNonce);
while (clientNonces.size() > 64) {
clientNonces.remove(0);
}
}
ByteString clientCertificateBytes = request.getClientCertificate();
if (securityPolicy != SecurityPolicy.None && serviceRequest.getClientCertificateBytes() != null) {
if (!Objects.equal(clientCertificateBytes, serviceRequest.getClientCertificateBytes())) {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed, "certificate used to open secure channel " + "differs from certificate used to create session");
}
}
SecurityConfiguration securityConfiguration = createSecurityConfiguration(endpoint, clientCertificateBytes);
if (securityPolicy != SecurityPolicy.None) {
X509Certificate clientCertificate = securityConfiguration.getClientCertificate();
List<X509Certificate> clientCertificateChain = securityConfiguration.getClientCertificateChain();
if (clientCertificate == null || clientCertificateChain == null) {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed, "client certificate must be non-null");
}
ServerCertificateValidator certificateValidator = server.getConfig().getCertificateValidator();
certificateValidator.validateCertificateChain(clientCertificateChain, clientDescription.getApplicationUri());
}
// SignatureData must be created using only the bytes of the client
// leaf certificate, not the bytes of the client certificate chain.
SignatureData serverSignature = getServerSignature(securityPolicy, securityConfiguration.getKeyPair(), clientNonce, securityConfiguration.getClientCertificateBytes());
NodeId sessionId = new NodeId(1, "Session:" + UUID.randomUUID());
String sessionName = request.getSessionName();
Duration sessionTimeout = Duration.ofMillis(DoubleMath.roundToLong(revisedSessionTimeout, RoundingMode.UP));
Session session = new Session(server, sessionId, sessionName, sessionTimeout, clientDescription, request.getServerUri(), request.getMaxResponseMessageSize(), endpoint, secureChannelId, securityConfiguration);
session.setLastNonce(serverNonce);
session.addLifecycleListener((s, remove) -> {
createdSessions.remove(authenticationToken);
activeSessions.remove(authenticationToken);
sessionListeners.forEach(l -> l.onSessionClosed(s));
});
createdSessions.put(authenticationToken, session);
sessionListeners.forEach(l -> l.onSessionCreated(session));
return new CreateSessionResponse(serviceRequest.createResponseHeader(), sessionId, authenticationToken, revisedSessionTimeout, serverNonce, endpoint.getServerCertificate(), serverEndpoints, new SignedSoftwareCertificate[0], serverSignature, uint(maxRequestMessageSize));
}
Aggregations