ua_client_connect.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  4. *
  5. * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
  6. * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
  7. * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  8. * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  9. * Copyright 2018 (c) Kalycito Infotech Private Limited
  10. */
  11. #include "ua_client.h"
  12. #include "ua_client_internal.h"
  13. #include "ua_transport_generated.h"
  14. #include "ua_transport_generated_handling.h"
  15. #include "ua_transport_generated_encoding_binary.h"
  16. #include "ua_types_encoding_binary.h"
  17. #include "ua_types_generated_encoding_binary.h"
  18. /* Size are refered in bytes */
  19. #define UA_MINMESSAGESIZE 8192
  20. #define UA_SESSION_LOCALNONCELENGTH 32
  21. #define MAX_DATA_SIZE 4096
  22. /********************/
  23. /* Set client state */
  24. /********************/
  25. void
  26. setClientState(UA_Client *client, UA_ClientState state) {
  27. if(client->state != state) {
  28. client->state = state;
  29. if(client->config.stateCallback)
  30. client->config.stateCallback(client, client->state);
  31. }
  32. }
  33. /***********************/
  34. /* Open the Connection */
  35. /***********************/
  36. #define UA_BITMASK_MESSAGETYPE 0x00ffffff
  37. #define UA_BITMASK_CHUNKTYPE 0xff000000
  38. static UA_StatusCode
  39. processACKResponse(void *application, UA_Connection *connection, UA_ByteString *chunk) {
  40. UA_Client *client = (UA_Client*)application;
  41. /* Decode the message */
  42. size_t offset = 0;
  43. UA_StatusCode retval;
  44. UA_TcpMessageHeader messageHeader;
  45. UA_TcpAcknowledgeMessage ackMessage;
  46. retval = UA_TcpMessageHeader_decodeBinary(chunk, &offset, &messageHeader);
  47. if(retval != UA_STATUSCODE_GOOD) {
  48. UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK,
  49. "Decoding ACK message failed");
  50. return retval;
  51. }
  52. // check if we got an error response from the server
  53. UA_MessageType messageType = (UA_MessageType)
  54. (messageHeader.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE);
  55. UA_ChunkType chunkType = (UA_ChunkType)
  56. (messageHeader.messageTypeAndChunkType & UA_BITMASK_CHUNKTYPE);
  57. if (messageType == UA_MESSAGETYPE_ERR) {
  58. // Header + ErrorMessage (error + reasonLength_field + length)
  59. UA_StatusCode error = *(UA_StatusCode*)(&chunk->data[offset]);
  60. UA_UInt32 len = *((UA_UInt32*)&chunk->data[offset + 4]);
  61. UA_Byte *data = (UA_Byte*)&chunk->data[offset + 4+4];
  62. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_NETWORK,
  63. "Received ERR response. %s - %.*s", UA_StatusCode_name(error), len, data);
  64. return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
  65. }
  66. if (chunkType != UA_CHUNKTYPE_FINAL) {
  67. return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
  68. }
  69. retval |= UA_TcpAcknowledgeMessage_decodeBinary(chunk, &offset, &ackMessage);
  70. if(retval != UA_STATUSCODE_GOOD) {
  71. UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK,
  72. "Decoding ACK message failed");
  73. return retval;
  74. }
  75. /* Store remote connection settings and adjust local configuration to not
  76. * exceed the limits */
  77. UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_NETWORK, "Received ACK message");
  78. connection->remoteConf.maxChunkCount = ackMessage.maxChunkCount; /* may be zero -> unlimited */
  79. connection->remoteConf.maxMessageSize = ackMessage.maxMessageSize; /* may be zero -> unlimited */
  80. connection->remoteConf.protocolVersion = ackMessage.protocolVersion;
  81. connection->remoteConf.sendBufferSize = ackMessage.sendBufferSize;
  82. connection->remoteConf.recvBufferSize = ackMessage.receiveBufferSize;
  83. if(connection->remoteConf.recvBufferSize < connection->localConf.sendBufferSize)
  84. connection->localConf.sendBufferSize = connection->remoteConf.recvBufferSize;
  85. if(connection->remoteConf.sendBufferSize < connection->localConf.recvBufferSize)
  86. connection->localConf.recvBufferSize = connection->remoteConf.sendBufferSize;
  87. connection->state = UA_CONNECTION_ESTABLISHED;
  88. return UA_STATUSCODE_GOOD;
  89. }
  90. static UA_StatusCode
  91. HelAckHandshake(UA_Client *client) {
  92. /* Get a buffer */
  93. UA_ByteString message;
  94. UA_Connection *conn = &client->connection;
  95. UA_StatusCode retval = conn->getSendBuffer(conn, UA_MINMESSAGESIZE, &message);
  96. if(retval != UA_STATUSCODE_GOOD)
  97. return retval;
  98. /* Prepare the HEL message and encode at offset 8 */
  99. UA_TcpHelloMessage hello;
  100. UA_String_copy(&client->endpointUrl, &hello.endpointUrl); /* must be less than 4096 bytes */
  101. hello.maxChunkCount = conn->localConf.maxChunkCount;
  102. hello.maxMessageSize = conn->localConf.maxMessageSize;
  103. hello.protocolVersion = conn->localConf.protocolVersion;
  104. hello.receiveBufferSize = conn->localConf.recvBufferSize;
  105. hello.sendBufferSize = conn->localConf.sendBufferSize;
  106. UA_Byte *bufPos = &message.data[8]; /* skip the header */
  107. const UA_Byte *bufEnd = &message.data[message.length];
  108. retval = UA_TcpHelloMessage_encodeBinary(&hello, &bufPos, bufEnd);
  109. UA_TcpHelloMessage_deleteMembers(&hello);
  110. /* Encode the message header at offset 0 */
  111. UA_TcpMessageHeader messageHeader;
  112. messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_HEL;
  113. messageHeader.messageSize = (UA_UInt32)((uintptr_t)bufPos - (uintptr_t)message.data);
  114. bufPos = message.data;
  115. retval |= UA_TcpMessageHeader_encodeBinary(&messageHeader, &bufPos, bufEnd);
  116. if(retval != UA_STATUSCODE_GOOD) {
  117. conn->releaseSendBuffer(conn, &message);
  118. return retval;
  119. }
  120. /* Send the HEL message */
  121. message.length = messageHeader.messageSize;
  122. retval = conn->send(conn, &message);
  123. if(retval != UA_STATUSCODE_GOOD) {
  124. UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK,
  125. "Sending HEL failed");
  126. return retval;
  127. }
  128. UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_NETWORK,
  129. "Sent HEL message");
  130. /* Loop until we have a complete chunk */
  131. retval = UA_Connection_receiveChunksBlocking(conn, client, processACKResponse,
  132. client->config.timeout);
  133. if(retval != UA_STATUSCODE_GOOD) {
  134. UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK,
  135. "Receiving ACK message failed");
  136. if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED)
  137. client->state = UA_CLIENTSTATE_DISCONNECTED;
  138. UA_Client_close(client);
  139. }
  140. return retval;
  141. }
  142. static void
  143. processDecodedOPNResponse(UA_Client *client, UA_OpenSecureChannelResponse *response, UA_Boolean renew) {
  144. /* Replace the token */
  145. if (renew)
  146. client->channel.nextSecurityToken = response->securityToken; // Set the next token
  147. else
  148. client->channel.securityToken = response->securityToken; // Set initial token
  149. /* Replace the nonce */
  150. UA_ByteString_deleteMembers(&client->channel.remoteNonce);
  151. client->channel.remoteNonce = response->serverNonce;
  152. UA_ByteString_init(&response->serverNonce);
  153. if(client->channel.state == UA_SECURECHANNELSTATE_OPEN)
  154. UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
  155. "SecureChannel in the server renewed");
  156. else
  157. UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
  158. "Opened SecureChannel acknowledged by the server");
  159. /* Response.securityToken.revisedLifetime is UInt32 we need to cast it to
  160. * DateTime=Int64 we take 75% of lifetime to start renewing as described in
  161. * standard */
  162. client->channel.state = UA_SECURECHANNELSTATE_OPEN;
  163. client->nextChannelRenewal = UA_DateTime_nowMonotonic() + (UA_DateTime)
  164. (client->channel.securityToken.revisedLifetime * (UA_Double)UA_DATETIME_MSEC * 0.75);
  165. }
  166. static UA_StatusCode
  167. openSecureChannel(UA_Client *client, UA_Boolean renew) {
  168. /* Check if sc is still valid */
  169. if(renew && client->nextChannelRenewal > UA_DateTime_nowMonotonic())
  170. return UA_STATUSCODE_GOOD;
  171. UA_Connection *conn = &client->connection;
  172. if(conn->state != UA_CONNECTION_ESTABLISHED)
  173. return UA_STATUSCODE_BADSERVERNOTCONNECTED;
  174. /* Prepare the OpenSecureChannelRequest */
  175. UA_OpenSecureChannelRequest opnSecRq;
  176. UA_OpenSecureChannelRequest_init(&opnSecRq);
  177. opnSecRq.requestHeader.timestamp = UA_DateTime_now();
  178. opnSecRq.requestHeader.authenticationToken = client->authenticationToken;
  179. if(renew) {
  180. opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_RENEW;
  181. UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
  182. "Requesting to renew the SecureChannel");
  183. } else {
  184. opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
  185. UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
  186. "Requesting to open a SecureChannel");
  187. }
  188. /* Set the securityMode to input securityMode from client data */
  189. opnSecRq.securityMode = client->channel.securityMode;
  190. opnSecRq.clientNonce = client->channel.localNonce;
  191. opnSecRq.requestedLifetime = client->config.secureChannelLifeTime;
  192. /* Send the OPN message */
  193. UA_UInt32 requestId = ++client->requestId;
  194. UA_StatusCode retval =
  195. UA_SecureChannel_sendAsymmetricOPNMessage(&client->channel, requestId, &opnSecRq,
  196. &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST]);
  197. if(retval != UA_STATUSCODE_GOOD) {
  198. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
  199. "Sending OPN message failed with error %s", UA_StatusCode_name(retval));
  200. UA_Client_close(client);
  201. return retval;
  202. }
  203. UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "OPN message sent");
  204. /* Increase nextChannelRenewal to avoid that we re-start renewal when
  205. * publish responses are received before the OPN response arrives. */
  206. client->nextChannelRenewal = UA_DateTime_nowMonotonic() +
  207. (2 * ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC));
  208. /* Receive / decrypt / decode the OPN response. Process async services in
  209. * the background until the OPN response arrives. */
  210. UA_OpenSecureChannelResponse response;
  211. retval = receiveServiceResponse(client, &response,
  212. &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE],
  213. UA_DateTime_nowMonotonic() +
  214. ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC),
  215. &requestId);
  216. if(retval != UA_STATUSCODE_GOOD) {
  217. UA_Client_close(client);
  218. return retval;
  219. }
  220. processDecodedOPNResponse(client, &response, renew);
  221. UA_OpenSecureChannelResponse_deleteMembers(&response);
  222. return retval;
  223. }
  224. /* Function to verify the signature corresponds to ClientNonce
  225. * using the local certificate.
  226. *
  227. * @param channel current channel in which the client runs
  228. * @param response create session response from the server
  229. * @return Returns an error code or UA_STATUSCODE_GOOD. */
  230. static UA_StatusCode
  231. checkClientSignature(const UA_SecureChannel *channel, const UA_CreateSessionResponse *response) {
  232. if(channel == NULL || response == NULL)
  233. return UA_STATUSCODE_BADINTERNALERROR;
  234. if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
  235. channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
  236. return UA_STATUSCODE_GOOD;
  237. if(!channel->securityPolicy)
  238. return UA_STATUSCODE_BADINTERNALERROR;
  239. const UA_SecurityPolicy* securityPolicy = channel->securityPolicy;
  240. const UA_ByteString* localCertificate = &securityPolicy->localCertificate;
  241. size_t dataToVerifySize = localCertificate->length + channel->localNonce.length;
  242. UA_ByteString dataToVerify = UA_BYTESTRING_NULL;
  243. UA_StatusCode retval = UA_ByteString_allocBuffer(&dataToVerify, dataToVerifySize);
  244. if(retval != UA_STATUSCODE_GOOD)
  245. return retval;
  246. memcpy(dataToVerify.data, localCertificate->data, localCertificate->length);
  247. memcpy(dataToVerify.data + localCertificate->length,
  248. channel->localNonce.data, channel->localNonce.length);
  249. retval = securityPolicy->
  250. certificateSigningAlgorithm.verify(securityPolicy,
  251. channel->channelContext,
  252. &dataToVerify,
  253. &response->serverSignature.signature);
  254. UA_ByteString_deleteMembers(&dataToVerify);
  255. return retval;
  256. }
  257. /* Function to create a signature using remote certificate and nonce
  258. *
  259. * @param channel current channel in which the client runs
  260. * @param request activate session request message to server
  261. * @return Returns an error or UA_STATUSCODE_GOOD */
  262. static UA_StatusCode
  263. signActivateSessionRequest(UA_SecureChannel *channel,
  264. UA_ActivateSessionRequest *request) {
  265. if(channel == NULL || request == NULL)
  266. return UA_STATUSCODE_BADINTERNALERROR;
  267. if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
  268. channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
  269. return UA_STATUSCODE_GOOD;
  270. const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
  271. UA_SignatureData *signatureData = &request->clientSignature;
  272. /* Prepare the signature */
  273. size_t signatureSize = securityPolicy->certificateSigningAlgorithm.
  274. getLocalSignatureSize(securityPolicy, channel->channelContext);
  275. UA_StatusCode retval = UA_String_copy(&securityPolicy->certificateSigningAlgorithm.uri,
  276. &signatureData->algorithm);
  277. if(retval != UA_STATUSCODE_GOOD)
  278. return retval;
  279. retval = UA_ByteString_allocBuffer(&signatureData->signature, signatureSize);
  280. if(retval != UA_STATUSCODE_GOOD)
  281. return retval;
  282. /* Allocate a temporary buffer */
  283. size_t dataToSignSize = channel->remoteCertificate.length + channel->remoteNonce.length;
  284. /* Prevent stack-smashing. TODO: Compute MaxSenderCertificateSize */
  285. if(dataToSignSize > MAX_DATA_SIZE)
  286. return UA_STATUSCODE_BADINTERNALERROR;
  287. UA_ByteString dataToSign;
  288. retval = UA_ByteString_allocBuffer(&dataToSign, dataToSignSize);
  289. if(retval != UA_STATUSCODE_GOOD)
  290. return retval; /* signatureData->signature is cleaned up with the response */
  291. /* Sign the signature */
  292. memcpy(dataToSign.data, channel->remoteCertificate.data, channel->remoteCertificate.length);
  293. memcpy(dataToSign.data + channel->remoteCertificate.length,
  294. channel->remoteNonce.data, channel->remoteNonce.length);
  295. retval = securityPolicy->certificateSigningAlgorithm.
  296. sign(securityPolicy, channel->channelContext, &dataToSign,
  297. &signatureData->signature);
  298. /* Clean up */
  299. UA_ByteString_deleteMembers(&dataToSign);
  300. return retval;
  301. }
  302. static UA_StatusCode
  303. activateSession(UA_Client *client) {
  304. UA_ActivateSessionRequest request;
  305. UA_ActivateSessionRequest_init(&request);
  306. request.requestHeader.requestHandle = ++client->requestHandle;
  307. request.requestHeader.timestamp = UA_DateTime_now();
  308. request.requestHeader.timeoutHint = 600000;
  309. //manual ExtensionObject encoding of the identityToken
  310. if(client->authenticationMethod == UA_CLIENTAUTHENTICATION_NONE) {
  311. UA_AnonymousIdentityToken* identityToken = UA_AnonymousIdentityToken_new();
  312. UA_AnonymousIdentityToken_init(identityToken);
  313. UA_String_copy(&client->token.policyId, &identityToken->policyId);
  314. request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
  315. request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN];
  316. request.userIdentityToken.content.decoded.data = identityToken;
  317. } else {
  318. UA_UserNameIdentityToken* identityToken = UA_UserNameIdentityToken_new();
  319. UA_UserNameIdentityToken_init(identityToken);
  320. UA_String_copy(&client->token.policyId, &identityToken->policyId);
  321. UA_String_copy(&client->username, &identityToken->userName);
  322. UA_String_copy(&client->password, &identityToken->password);
  323. request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
  324. request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN];
  325. request.userIdentityToken.content.decoded.data = identityToken;
  326. }
  327. /* This function call is to prepare a client signature */
  328. if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
  329. client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
  330. signActivateSessionRequest(&client->channel, &request);
  331. }
  332. UA_ActivateSessionResponse response;
  333. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
  334. &response, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
  335. if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
  336. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
  337. "ActivateSession failed with error code %s",
  338. UA_StatusCode_name(response.responseHeader.serviceResult));
  339. }
  340. UA_StatusCode retval = response.responseHeader.serviceResult;
  341. UA_ActivateSessionRequest_deleteMembers(&request);
  342. UA_ActivateSessionResponse_deleteMembers(&response);
  343. return retval;
  344. }
  345. /* Gets a list of endpoints. Memory is allocated for endpointDescription array */
  346. UA_StatusCode
  347. UA_Client_getEndpointsInternal(UA_Client *client, size_t* endpointDescriptionsSize,
  348. UA_EndpointDescription** endpointDescriptions) {
  349. UA_GetEndpointsRequest request;
  350. UA_GetEndpointsRequest_init(&request);
  351. request.requestHeader.timestamp = UA_DateTime_now();
  352. request.requestHeader.timeoutHint = 10000;
  353. // assume the endpointurl outlives the service call
  354. request.endpointUrl = client->endpointUrl;
  355. UA_GetEndpointsResponse response;
  356. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
  357. &response, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
  358. if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
  359. UA_StatusCode retval = response.responseHeader.serviceResult;
  360. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
  361. "GetEndpointRequest failed with error code %s",
  362. UA_StatusCode_name(retval));
  363. UA_GetEndpointsResponse_deleteMembers(&response);
  364. return retval;
  365. }
  366. *endpointDescriptions = response.endpoints;
  367. *endpointDescriptionsSize = response.endpointsSize;
  368. response.endpoints = NULL;
  369. response.endpointsSize = 0;
  370. UA_GetEndpointsResponse_deleteMembers(&response);
  371. return UA_STATUSCODE_GOOD;
  372. }
  373. static UA_StatusCode
  374. getEndpoints(UA_Client *client) {
  375. UA_EndpointDescription* endpointArray = NULL;
  376. size_t endpointArraySize = 0;
  377. UA_StatusCode retval =
  378. UA_Client_getEndpointsInternal(client, &endpointArraySize, &endpointArray);
  379. if(retval != UA_STATUSCODE_GOOD)
  380. return retval;
  381. UA_Boolean endpointFound = false;
  382. UA_Boolean tokenFound = false;
  383. UA_String securityNone = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
  384. UA_String binaryTransport = UA_STRING("http://opcfoundation.org/UA-Profile/"
  385. "Transport/uatcp-uasc-uabinary");
  386. // TODO: compare endpoint information with client->endpointUri
  387. for(size_t i = 0; i < endpointArraySize; ++i) {
  388. UA_EndpointDescription* endpoint = &endpointArray[i];
  389. /* look out for binary transport endpoints */
  390. /* Note: Siemens returns empty ProfileUrl, we will accept it as binary */
  391. if(endpoint->transportProfileUri.length != 0 &&
  392. !UA_String_equal(&endpoint->transportProfileUri, &binaryTransport))
  393. continue;
  394. /* look for an endpoint corresponding to the client security policy */
  395. if(!UA_String_equal(&endpoint->securityPolicyUri, &client->securityPolicy.policyUri))
  396. continue;
  397. endpointFound = true;
  398. /* look for a user token policy with an anonymous token */
  399. for(size_t j = 0; j < endpoint->userIdentityTokensSize; ++j) {
  400. UA_UserTokenPolicy* userToken = &endpoint->userIdentityTokens[j];
  401. /* Usertokens also have a security policy... */
  402. if(userToken->securityPolicyUri.length > 0 &&
  403. !UA_String_equal(&userToken->securityPolicyUri, &securityNone))
  404. continue;
  405. /* UA_CLIENTAUTHENTICATION_NONE == UA_USERTOKENTYPE_ANONYMOUS
  406. * UA_CLIENTAUTHENTICATION_USERNAME == UA_USERTOKENTYPE_USERNAME
  407. * TODO: Check equivalence for other types when adding the support */
  408. if((int)client->authenticationMethod != (int)userToken->tokenType)
  409. continue;
  410. /* Endpoint with matching usertokenpolicy found */
  411. tokenFound = true;
  412. UA_UserTokenPolicy_deleteMembers(&client->token);
  413. UA_UserTokenPolicy_copy(userToken, &client->token);
  414. break;
  415. }
  416. }
  417. UA_Array_delete(endpointArray, endpointArraySize,
  418. &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
  419. if(!endpointFound) {
  420. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
  421. "No suitable endpoint found");
  422. retval = UA_STATUSCODE_BADINTERNALERROR;
  423. } else if(!tokenFound) {
  424. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
  425. "No suitable UserTokenPolicy found for the possible endpoints");
  426. retval = UA_STATUSCODE_BADINTERNALERROR;
  427. }
  428. return retval;
  429. }
  430. static UA_StatusCode
  431. createSession(UA_Client *client) {
  432. UA_CreateSessionRequest request;
  433. UA_CreateSessionRequest_init(&request);
  434. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  435. if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
  436. client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
  437. if(client->channel.localNonce.length != UA_SESSION_LOCALNONCELENGTH) {
  438. UA_ByteString_deleteMembers(&client->channel.localNonce);
  439. retval = UA_ByteString_allocBuffer(&client->channel.localNonce,
  440. UA_SESSION_LOCALNONCELENGTH);
  441. if(retval != UA_STATUSCODE_GOOD)
  442. return retval;
  443. }
  444. retval = client->channel.securityPolicy->symmetricModule.
  445. generateNonce(client->channel.securityPolicy, &client->channel.localNonce);
  446. if(retval != UA_STATUSCODE_GOOD)
  447. return retval;
  448. }
  449. request.requestHeader.timestamp = UA_DateTime_now();
  450. request.requestHeader.timeoutHint = 10000;
  451. UA_ByteString_copy(&client->channel.localNonce, &request.clientNonce);
  452. request.requestedSessionTimeout = 1200000;
  453. request.maxResponseMessageSize = UA_INT32_MAX;
  454. UA_String_copy(&client->endpointUrl, &request.endpointUrl);
  455. if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
  456. client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
  457. UA_ByteString_copy(&client->channel.securityPolicy->localCertificate,
  458. &request.clientCertificate);
  459. }
  460. UA_CreateSessionResponse response;
  461. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
  462. &response, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
  463. if(response.responseHeader.serviceResult == UA_STATUSCODE_GOOD &&
  464. (client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
  465. client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)) {
  466. UA_ByteString_deleteMembers(&client->channel.remoteNonce);
  467. UA_ByteString_copy(&response.serverNonce, &client->channel.remoteNonce);
  468. if(!UA_ByteString_equal(&response.serverCertificate,
  469. &client->channel.remoteCertificate)) {
  470. return UA_STATUSCODE_BADCERTIFICATEINVALID;
  471. }
  472. /* Verify the client signature */
  473. retval = checkClientSignature(&client->channel, &response);
  474. if(retval != UA_STATUSCODE_GOOD)
  475. return retval;
  476. }
  477. UA_NodeId_copy(&response.authenticationToken, &client->authenticationToken);
  478. retval = response.responseHeader.serviceResult;
  479. UA_CreateSessionRequest_deleteMembers(&request);
  480. UA_CreateSessionResponse_deleteMembers(&response);
  481. return retval;
  482. }
  483. UA_StatusCode
  484. UA_Client_connectInternal(UA_Client *client, const char *endpointUrl,
  485. UA_Boolean endpointsHandshake, UA_Boolean createNewSession) {
  486. if(client->state >= UA_CLIENTSTATE_CONNECTED)
  487. return UA_STATUSCODE_GOOD;
  488. UA_ChannelSecurityToken_init(&client->channel.securityToken);
  489. client->channel.state = UA_SECURECHANNELSTATE_FRESH;
  490. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  491. client->connection =
  492. client->config.connectionFunc(client->config.localConnectionConfig,
  493. endpointUrl, client->config.timeout,
  494. client->config.logger);
  495. if(client->connection.state != UA_CONNECTION_OPENING) {
  496. retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
  497. goto cleanup;
  498. }
  499. UA_String_deleteMembers(&client->endpointUrl);
  500. client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
  501. if(!client->endpointUrl.data) {
  502. retval = UA_STATUSCODE_BADOUTOFMEMORY;
  503. goto cleanup;
  504. }
  505. /* Local nonce set and generate sym keys */
  506. retval |= UA_SecureChannel_generateLocalNonce(&client->channel);
  507. if(retval != UA_STATUSCODE_GOOD)
  508. return retval;
  509. /* Open a TCP connection */
  510. client->connection.localConf = client->config.localConnectionConfig;
  511. retval = HelAckHandshake(client);
  512. if(retval != UA_STATUSCODE_GOOD)
  513. goto cleanup;
  514. setClientState(client, UA_CLIENTSTATE_CONNECTED);
  515. /* Open a SecureChannel. TODO: Select with endpoint */
  516. client->channel.connection = &client->connection;
  517. retval = openSecureChannel(client, false);
  518. if(retval != UA_STATUSCODE_GOOD)
  519. goto cleanup;
  520. setClientState(client, UA_CLIENTSTATE_SECURECHANNEL);
  521. /* Delete async service. TODO: Move this from connect to the disconnect/cleanup phase */
  522. UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSHUTDOWN);
  523. #ifdef UA_ENABLE_SUBSCRIPTIONS
  524. client->currentlyOutStandingPublishRequests = 0;
  525. #endif
  526. // TODO: actually, reactivate an existing session is working, but currently republish is not implemented
  527. // This option is disabled until we have a good implementation of the subscription recovery.
  528. #ifdef UA_SESSION_RECOVERY
  529. /* Try to activate an existing Session for this SecureChannel */
  530. if((!UA_NodeId_equal(&client->authenticationToken, &UA_NODEID_NULL)) && (createNewSession)) {
  531. retval = activateSession(client);
  532. if(retval == UA_STATUSCODE_BADSESSIONIDINVALID) {
  533. /* Could not recover an old session. Remove authenticationToken */
  534. UA_NodeId_deleteMembers(&client->authenticationToken);
  535. } else {
  536. if(retval != UA_STATUSCODE_GOOD)
  537. goto cleanup;
  538. setClientState(client, UA_CLIENTSTATE_SESSION_RENEWED);
  539. return retval;
  540. }
  541. } else {
  542. UA_NodeId_deleteMembers(&client->authenticationToken);
  543. }
  544. #else
  545. UA_NodeId_deleteMembers(&client->authenticationToken);
  546. #endif /* UA_SESSION_RECOVERY */
  547. /* Generate new local and remote key */
  548. retval |= UA_SecureChannel_generateNewKeys(&client->channel);
  549. if(retval != UA_STATUSCODE_GOOD)
  550. return retval;
  551. /* Get Endpoints */
  552. if(endpointsHandshake) {
  553. retval = getEndpoints(client);
  554. if(retval != UA_STATUSCODE_GOOD)
  555. goto cleanup;
  556. }
  557. /* Create the Session for this SecureChannel */
  558. if(createNewSession) {
  559. retval = createSession(client);
  560. if(retval != UA_STATUSCODE_GOOD)
  561. goto cleanup;
  562. #ifdef UA_ENABLE_SUBSCRIPTIONS
  563. /* A new session has been created. We need to clean up the subscriptions */
  564. UA_Client_Subscriptions_clean(client);
  565. #endif
  566. retval = activateSession(client);
  567. if(retval != UA_STATUSCODE_GOOD)
  568. goto cleanup;
  569. setClientState(client, UA_CLIENTSTATE_SESSION);
  570. }
  571. return retval;
  572. cleanup:
  573. UA_Client_close(client);
  574. return retval;
  575. }
  576. UA_StatusCode
  577. UA_Client_connect(UA_Client *client, const char *endpointUrl) {
  578. return UA_Client_connectInternal(client, endpointUrl, UA_TRUE, UA_TRUE);
  579. }
  580. UA_StatusCode
  581. UA_Client_connect_noSession(UA_Client *client, const char *endpointUrl) {
  582. return UA_Client_connectInternal(client, endpointUrl, UA_TRUE, UA_FALSE);
  583. }
  584. UA_StatusCode
  585. UA_Client_connect_username(UA_Client *client, const char *endpointUrl,
  586. const char *username, const char *password) {
  587. client->authenticationMethod = UA_CLIENTAUTHENTICATION_USERNAME;
  588. client->username = UA_STRING_ALLOC(username);
  589. client->password = UA_STRING_ALLOC(password);
  590. return UA_Client_connect(client, endpointUrl);
  591. }
  592. UA_StatusCode
  593. UA_Client_manuallyRenewSecureChannel(UA_Client *client) {
  594. UA_StatusCode retval = openSecureChannel(client, true);
  595. if(retval != UA_STATUSCODE_GOOD)
  596. UA_Client_close(client);
  597. return retval;
  598. }
  599. /************************/
  600. /* Close the Connection */
  601. /************************/
  602. static void
  603. sendCloseSession(UA_Client *client) {
  604. UA_CloseSessionRequest request;
  605. UA_CloseSessionRequest_init(&request);
  606. request.requestHeader.timestamp = UA_DateTime_now();
  607. request.requestHeader.timeoutHint = 10000;
  608. request.deleteSubscriptions = true;
  609. UA_CloseSessionResponse response;
  610. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
  611. &response, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
  612. UA_CloseSessionRequest_deleteMembers(&request);
  613. UA_CloseSessionResponse_deleteMembers(&response);
  614. }
  615. static void
  616. sendCloseSecureChannel(UA_Client *client) {
  617. UA_SecureChannel *channel = &client->channel;
  618. UA_CloseSecureChannelRequest request;
  619. UA_CloseSecureChannelRequest_init(&request);
  620. request.requestHeader.requestHandle = ++client->requestHandle;
  621. request.requestHeader.timestamp = UA_DateTime_now();
  622. request.requestHeader.timeoutHint = 10000;
  623. request.requestHeader.authenticationToken = client->authenticationToken;
  624. UA_SecureChannel_sendSymmetricMessage(channel, ++client->requestId,
  625. UA_MESSAGETYPE_CLO, &request,
  626. &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
  627. UA_CloseSecureChannelRequest_deleteMembers(&request);
  628. UA_SecureChannel_deleteMembersCleanup(&client->channel);
  629. }
  630. UA_StatusCode
  631. UA_Client_disconnect(UA_Client *client) {
  632. /* Is a session established? */
  633. if(client->state >= UA_CLIENTSTATE_SESSION) {
  634. client->state = UA_CLIENTSTATE_SECURECHANNEL;
  635. sendCloseSession(client);
  636. }
  637. UA_NodeId_deleteMembers(&client->authenticationToken);
  638. client->requestHandle = 0;
  639. /* Is a secure channel established? */
  640. if(client->state >= UA_CLIENTSTATE_SECURECHANNEL) {
  641. client->state = UA_CLIENTSTATE_CONNECTED;
  642. sendCloseSecureChannel(client);
  643. }
  644. /* Close the TCP connection */
  645. if(client->connection.state != UA_CONNECTION_CLOSED)
  646. client->connection.close(&client->connection);
  647. #ifdef UA_ENABLE_SUBSCRIPTIONS
  648. // TODO REMOVE WHEN UA_SESSION_RECOVERY IS READY
  649. /* We need to clean up the subscriptions */
  650. UA_Client_Subscriptions_clean(client);
  651. #endif
  652. setClientState(client, UA_CLIENTSTATE_DISCONNECTED);
  653. return UA_STATUSCODE_GOOD;
  654. }
  655. UA_StatusCode
  656. UA_Client_close(UA_Client *client) {
  657. client->requestHandle = 0;
  658. if(client->state >= UA_CLIENTSTATE_SECURECHANNEL)
  659. UA_SecureChannel_deleteMembersCleanup(&client->channel);
  660. /* Close the TCP connection */
  661. if(client->connection.state != UA_CONNECTION_CLOSED)
  662. client->connection.close(&client->connection);
  663. #ifdef UA_ENABLE_SUBSCRIPTIONS
  664. // TODO REMOVE WHEN UA_SESSION_RECOVERY IS READY
  665. /* We need to clean up the subscriptions */
  666. UA_Client_Subscriptions_clean(client);
  667. #endif
  668. setClientState(client, UA_CLIENTSTATE_DISCONNECTED);
  669. return UA_STATUSCODE_GOOD;
  670. }