Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
serviceResult: serviceResult
},
serverProtocolVersion: self.protocolVersion,
securityToken: self.securityToken,
serverNonce: self.serverNonce
});
// get the clientCertificate from message securityHeader
// for convenience
self.clientCertificate = message.securityHeader ? message.securityHeader.senderCertificate : null;
let description;
// If the SecurityMode is not None then the Server shall verify that a SenderCertificate and a
// ReceiverCertificateThumbprint were specified in the SecurityHeader.
if (self.securityMode.value !== MessageSecurityMode.NONE.value) {
if (!_check_receiverCertificateThumbprint.call(self, self.clientSecurityHeader)) {
description =
"Server#OpenSecureChannelRequest : Invalid receiver certificate thumbprint : the thumbprint doesn't match server certificate !";
console.log(description.cyan);
response.responseHeader.serviceResult = StatusCodes.BadCertificateInvalid;
}
}
if (self.clientCertificate) {
const certificate_status = _check_certificate_validity(self.clientCertificate);
if (StatusCodes.Good !== certificate_status) {
description = "Sender Certificate Error";
console.log(description.cyan, certificate_status.toString().bgRed.yellow);
// OPCUA specification v1.02 part 6 page 42 $6.7.4
// If an error occurs after the Server has verified Message security it shall return a ServiceFault instead
// of a OpenSecureChannel response. The ServiceFault Message is described in Part 4, 7.28.
// which are two different nonce, with different size (although they share the same name )
self.clientNonce = crypto.randomBytes(32);
const request = new CreateSessionRequest({
clientDescription: applicationDescription,
serverUri: self.serverUri,
endpointUrl: self.endpointUrl,
sessionName: self._nextSessionName(),
clientNonce: self.clientNonce,
clientCertificate: self.getCertificate(),
requestedSessionTimeout: self.requestedSessionTimeout,
maxResponseMessageSize: 800000
});
/* a client Nonce must be provided if security mode is set*/
assert(self._secureChannel.securityMode === MessageSecurityMode.NONE || request.clientNonce !== null);
self.performMessageTransaction(request, function (err, response) {
if (!err) {
//xx console.log("xxxxx response",response.toString());
//xx console.log("xxxxx response",response.responseHeader.serviceResult);
if (response.responseHeader.serviceResult === StatusCodes.BadTooManySessions) {
err = new Error("Too Many Sessions : " + response.responseHeader.serviceResult.toString());
} else if (response.responseHeader.serviceResult === StatusCodes.Good) {
assert(response instanceof CreateSessionResponse);
// istanbul ignore next
if (!validateServerNonce(request.serverNonce)) {
return callback(new Error("invalid server Nonce"));
function validate_applicationUri(applicationUri, clientCertificate) {
// if session is insecure there is no need to check certificate information
if (channel.securityMode === MessageSecurityMode.NONE) {
return true; // assume correct
}
if (!clientCertificate || clientCertificate.length === 0) {
return true;// can't check
}
const e = exploreCertificate(clientCertificate);
const applicationUriFromCert = e.tbsCertificate.extensions.subjectAltName.uniformResourceIdentifier[0];
return applicationUriFromCert === applicationUri;
}
assert(_.isFunction(callback), "expecting a callback");
const self = this;
self.endpointUrl = endpointUrl;
debugLog("OPCUAClientBase#connect ", endpointUrl);
// prevent illegal call to connect
if (self._secureChannel !== null) {
setImmediate(function () {
callback(new Error("connect already called"), null);
});
return;
}
if (!self.serverCertificate && self.securityMode !== MessageSecurityMode.NONE) {
debugLog("OPCUAClient : getting serverCertificate");
// we have not been given the serverCertificate but this certificate
// is required as the connection is to be secured.
//
// Let's explore the server endpoint that matches our security settings
// This will give us the missing Certificate as well from the server itself.
// todo :
// Once we have the certificate, we cannot trust it straight away
// we have to verify that the certificate is valid and not outdated and not revoked.
// if the certificate is self-signed the certificate must appear in the trust certificate
// list.
// if the certificate has been certified by an Certificate Authority we have to
// verify that the certificates in the chain are valid and not revoked.
//
const cert = self.certificateFile || 'certificates/client_selfsigned_cert_2048.pem';
MessageBuilder.prototype._decrypt_OPN = function (binaryStream) {
assert(this.securityPolicy !== SecurityPolicy.None);
assert(this.securityPolicy !== SecurityPolicy.Invalid);
assert(this.securityMode !== MessageSecurityMode.NONE);
//xx assert(this.securityMode !== MessageSecurityMode.INVALID);
/* istanbul ignore next */
if (doDebug) {
debugLog("securityHeader", JSON.stringify(this.securityHeader, null, " "));
}
// OpcUA part 2 V 1.02 page 15
// 4.11 OPC UA Security Related Services
// [...]
// The OPC UA Client sends its Public Key in a Digital Certificate and secret information with the
// OpenSecureChannel service Message to the Server. This Message is secured by applying
// Asymmetric Encryption with the Server's Public Key and by generating Asymmetric Signatures with
// the Client's Private Key. However the Digital Certificate is sent unencrypted so that the receiver can
// use it to verify the Asymmetric Signature.
// [...]
if (this.securityPolicy === SecurityPolicy.Invalid) {
// this._report_error("SecurityPolicy");
// return false;
return true;
}
const msgType = this.messageHeader.msgType;
// check if security is active or not
if (this.securityPolicy === SecurityPolicy.None) {
this.securityMode = MessageSecurityMode.NONE;
assert(this.securityMode === MessageSecurityMode.NONE, "expecting securityMode = None when securityPolicy is None");
return true; // nothing to do
}
assert(this.securityMode !== MessageSecurityMode.NONE);
if (msgType === "OPN") {
return this._decrypt_OPN(binaryStream);
} else {
return this._decrypt_MSG(binaryStream);
}
};
self.messageChunker = new MessageChunker({
derivedKeys: null
});
self.defaultSecureTokenLifetime = options.defaultSecureTokenLifetime || 30000;
self.tokenRenewalInterval = options.tokenRenewalInterval || 0;
self.securityMode = options.securityMode || MessageSecurityMode.NONE;
self.securityPolicy = options.securityPolicy || SecurityPolicy.None;
self.serverCertificate = options.serverCertificate;
assert(self.securityMode !== MessageSecurityMode.INVALID, "invalid security Mode");
if (self.securityMode !== MessageSecurityMode.NONE) {
assert(self.serverCertificate instanceof Buffer, "Expecting a valid certificate when security mode is not None");
assert(self.securityPolicy !== SecurityPolicy.None, "Security Policy None is not a valid choice");
}
self.messageBuilder = new MessageBuilder();
self.messageBuilder.securityMode = self.securityMode;
self.messageBuilder.privateKey = self.getPrivateKey();
self._request_data = {};
self.messageBuilder
.on("message", _on_message_received.bind(this))
.on("start_chunk", function () {
// record tick2: when the first response chunk is received
// request_data._tick2 = get_clock_tick();
}).on("error", function (err, requestId) {
function _send_error(statusCode, description, message, callback) {
/* jshint validthis: true */
const self = this;
// turn of security mode as we haven't manage to set it to
self.securityMode = MessageSecurityMode.NONE;
// unexpected message type ! let close the channel
const err = new Error(description);
self.send_error_and_abort(statusCode, description, message, function() {
callback(err); // OK
});
}
function _on_initial_OpenSecureChannelRequest(message, callback) {
this.protocolVersion = 0;
this._sessions = [];
this._server_endpoints = [];
this._secureChannel = null;
this.defaultSecureTokenLifetime = options.defaultSecureTokenLifetime || 600000;
this.tokenRenewalInterval = options.tokenRenewalInterval || 0;
assert(_.isFinite(this.tokenRenewalInterval) && this.tokenRenewalInterval >= 0);
/**
* @property securityMode
* @type MessageSecurityMode
*/
this.securityMode = options.securityMode || MessageSecurityMode.NONE;
this.securityMode = MessageSecurityMode.get(this.securityMode);
/**
* @property securityPolicy
* @type {SecurityPolicy}
*/
this.securityPolicy = options.securityPolicy || toURI("None");
this.securityPolicy = SecurityPolicy.get(this.securityPolicy);
/**
* @property serverCertificate
* @type {Certificate}
*/
this.serverCertificate = options.serverCertificate || null;
/**