ua_client_connect.c 31 KB

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