ua_client_connect.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  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. /* Increase nextChannelRenewal to avoid that we re-start renewal when
  180. * publish responses are received before the OPN response arrives. */
  181. client->nextChannelRenewal = UA_DateTime_nowMonotonic() +
  182. (2 * ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC));
  183. /* Receive / decrypt / decode the OPN response. Process async services in
  184. * the background until the OPN response arrives. */
  185. UA_OpenSecureChannelResponse response;
  186. retval = receiveServiceResponse(client, &response,
  187. &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE],
  188. UA_DateTime_nowMonotonic() +
  189. ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC),
  190. &requestId);
  191. if(retval != UA_STATUSCODE_GOOD) {
  192. UA_Client_close(client);
  193. return retval;
  194. }
  195. processDecodedOPNResponse(client, &response);
  196. UA_OpenSecureChannelResponse_deleteMembers(&response);
  197. return retval;
  198. }
  199. /* Function to verify the signature corresponds to ClientNonce
  200. * using the local certificate.
  201. *
  202. * @param channel current channel in which the client runs
  203. * @param response create session response from the server
  204. * @return Returns an error code or UA_STATUSCODE_GOOD. */
  205. static UA_StatusCode
  206. checkClientSignature(const UA_SecureChannel *channel, const UA_CreateSessionResponse *response) {
  207. if(channel == NULL || response == NULL)
  208. return UA_STATUSCODE_BADINTERNALERROR;
  209. if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
  210. channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
  211. return UA_STATUSCODE_GOOD;
  212. if(!channel->securityPolicy)
  213. return UA_STATUSCODE_BADINTERNALERROR;
  214. const UA_SecurityPolicy* securityPolicy = channel->securityPolicy;
  215. const UA_ByteString* localCertificate = &securityPolicy->localCertificate;
  216. size_t dataToVerifySize = localCertificate->length + channel->localNonce.length;
  217. UA_ByteString dataToVerify = UA_BYTESTRING_NULL;
  218. UA_StatusCode retval = UA_ByteString_allocBuffer(&dataToVerify, dataToVerifySize);
  219. if(retval != UA_STATUSCODE_GOOD)
  220. return retval;
  221. memcpy(dataToVerify.data, localCertificate->data, localCertificate->length);
  222. memcpy(dataToVerify.data + localCertificate->length,
  223. channel->localNonce.data, channel->localNonce.length);
  224. retval = securityPolicy->
  225. certificateSigningAlgorithm.verify(securityPolicy,
  226. channel->channelContext,
  227. &dataToVerify,
  228. &response->serverSignature.signature);
  229. UA_ByteString_deleteMembers(&dataToVerify);
  230. return retval;
  231. }
  232. /* Function to create a signature using remote certificate and nonce
  233. *
  234. * @param channel current channel in which the client runs
  235. * @param request activate session request message to server
  236. * @return Returns an error or UA_STATUSCODE_GOOD */
  237. static UA_StatusCode
  238. signActivateSessionRequest(UA_SecureChannel *channel,
  239. UA_ActivateSessionRequest *request) {
  240. if(channel == NULL || request == NULL)
  241. return UA_STATUSCODE_BADINTERNALERROR;
  242. if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
  243. channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
  244. return UA_STATUSCODE_GOOD;
  245. const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
  246. UA_SignatureData *signatureData = &request->clientSignature;
  247. /* Prepare the signature */
  248. size_t signatureSize = securityPolicy->certificateSigningAlgorithm.
  249. getLocalSignatureSize(securityPolicy, channel->channelContext);
  250. UA_StatusCode retval = UA_String_copy(&securityPolicy->certificateSigningAlgorithm.uri,
  251. &signatureData->algorithm);
  252. if(retval != UA_STATUSCODE_GOOD)
  253. return retval;
  254. retval = UA_ByteString_allocBuffer(&signatureData->signature, signatureSize);
  255. if(retval != UA_STATUSCODE_GOOD)
  256. return retval;
  257. /* Allocate a temporary buffer */
  258. size_t dataToSignSize = channel->remoteCertificate.length + channel->remoteNonce.length;
  259. /* Prevent stack-smashing. TODO: Compute MaxSenderCertificateSize */
  260. if(dataToSignSize > MAX_DATA_SIZE)
  261. return UA_STATUSCODE_BADINTERNALERROR;
  262. UA_ByteString dataToSign;
  263. retval = UA_ByteString_allocBuffer(&dataToSign, dataToSignSize);
  264. if(retval != UA_STATUSCODE_GOOD)
  265. return retval; /* signatureData->signature is cleaned up with the response */
  266. /* Sign the signature */
  267. memcpy(dataToSign.data, channel->remoteCertificate.data, channel->remoteCertificate.length);
  268. memcpy(dataToSign.data + channel->remoteCertificate.length,
  269. channel->remoteNonce.data, channel->remoteNonce.length);
  270. retval = securityPolicy->certificateSigningAlgorithm.
  271. sign(securityPolicy, channel->channelContext, &dataToSign,
  272. &signatureData->signature);
  273. /* Clean up */
  274. UA_ByteString_deleteMembers(&dataToSign);
  275. return retval;
  276. }
  277. static UA_StatusCode
  278. activateSession(UA_Client *client) {
  279. UA_ActivateSessionRequest request;
  280. UA_ActivateSessionRequest_init(&request);
  281. request.requestHeader.requestHandle = ++client->requestHandle;
  282. request.requestHeader.timestamp = UA_DateTime_now();
  283. request.requestHeader.timeoutHint = 600000;
  284. //manual ExtensionObject encoding of the identityToken
  285. if(client->authenticationMethod == UA_CLIENTAUTHENTICATION_NONE) {
  286. UA_AnonymousIdentityToken* identityToken = UA_AnonymousIdentityToken_new();
  287. UA_AnonymousIdentityToken_init(identityToken);
  288. UA_String_copy(&client->token.policyId, &identityToken->policyId);
  289. request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
  290. request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN];
  291. request.userIdentityToken.content.decoded.data = identityToken;
  292. } else {
  293. UA_UserNameIdentityToken* identityToken = UA_UserNameIdentityToken_new();
  294. UA_UserNameIdentityToken_init(identityToken);
  295. UA_String_copy(&client->token.policyId, &identityToken->policyId);
  296. UA_String_copy(&client->username, &identityToken->userName);
  297. UA_String_copy(&client->password, &identityToken->password);
  298. request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
  299. request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN];
  300. request.userIdentityToken.content.decoded.data = identityToken;
  301. }
  302. /* This function call is to prepare a client signature */
  303. if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
  304. client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
  305. signActivateSessionRequest(&client->channel, &request);
  306. }
  307. UA_ActivateSessionResponse response;
  308. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
  309. &response, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
  310. if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
  311. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
  312. "ActivateSession failed with error code %s",
  313. UA_StatusCode_name(response.responseHeader.serviceResult));
  314. }
  315. UA_StatusCode retval = response.responseHeader.serviceResult;
  316. UA_ActivateSessionRequest_deleteMembers(&request);
  317. UA_ActivateSessionResponse_deleteMembers(&response);
  318. return retval;
  319. }
  320. /* Gets a list of endpoints. Memory is allocated for endpointDescription array */
  321. UA_StatusCode
  322. UA_Client_getEndpointsInternal(UA_Client *client, size_t* endpointDescriptionsSize,
  323. UA_EndpointDescription** endpointDescriptions) {
  324. UA_GetEndpointsRequest request;
  325. UA_GetEndpointsRequest_init(&request);
  326. request.requestHeader.timestamp = UA_DateTime_now();
  327. request.requestHeader.timeoutHint = 10000;
  328. // assume the endpointurl outlives the service call
  329. request.endpointUrl = client->endpointUrl;
  330. UA_GetEndpointsResponse response;
  331. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
  332. &response, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
  333. if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
  334. UA_StatusCode retval = response.responseHeader.serviceResult;
  335. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
  336. "GetEndpointRequest failed with error code %s",
  337. UA_StatusCode_name(retval));
  338. UA_GetEndpointsResponse_deleteMembers(&response);
  339. return retval;
  340. }
  341. *endpointDescriptions = response.endpoints;
  342. *endpointDescriptionsSize = response.endpointsSize;
  343. response.endpoints = NULL;
  344. response.endpointsSize = 0;
  345. UA_GetEndpointsResponse_deleteMembers(&response);
  346. return UA_STATUSCODE_GOOD;
  347. }
  348. static UA_StatusCode
  349. getEndpoints(UA_Client *client) {
  350. UA_EndpointDescription* endpointArray = NULL;
  351. size_t endpointArraySize = 0;
  352. UA_StatusCode retval =
  353. UA_Client_getEndpointsInternal(client, &endpointArraySize, &endpointArray);
  354. if(retval != UA_STATUSCODE_GOOD)
  355. return retval;
  356. UA_Boolean endpointFound = false;
  357. UA_Boolean tokenFound = false;
  358. UA_String securityNone = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
  359. UA_String binaryTransport = UA_STRING("http://opcfoundation.org/UA-Profile/"
  360. "Transport/uatcp-uasc-uabinary");
  361. // TODO: compare endpoint information with client->endpointUri
  362. for(size_t i = 0; i < endpointArraySize; ++i) {
  363. UA_EndpointDescription* endpoint = &endpointArray[i];
  364. /* look out for binary transport endpoints */
  365. /* Note: Siemens returns empty ProfileUrl, we will accept it as binary */
  366. if(endpoint->transportProfileUri.length != 0 &&
  367. !UA_String_equal(&endpoint->transportProfileUri, &binaryTransport))
  368. continue;
  369. /* look for an endpoint corresponding to the client security policy */
  370. if(!UA_String_equal(&endpoint->securityPolicyUri, &client->securityPolicy.policyUri))
  371. continue;
  372. endpointFound = true;
  373. /* look for a user token policy with an anonymous token */
  374. for(size_t j = 0; j < endpoint->userIdentityTokensSize; ++j) {
  375. UA_UserTokenPolicy* userToken = &endpoint->userIdentityTokens[j];
  376. /* Usertokens also have a security policy... */
  377. if(userToken->securityPolicyUri.length > 0 &&
  378. !UA_String_equal(&userToken->securityPolicyUri, &securityNone))
  379. continue;
  380. /* UA_CLIENTAUTHENTICATION_NONE == UA_USERTOKENTYPE_ANONYMOUS
  381. * UA_CLIENTAUTHENTICATION_USERNAME == UA_USERTOKENTYPE_USERNAME
  382. * TODO: Check equivalence for other types when adding the support */
  383. if((int)client->authenticationMethod != (int)userToken->tokenType)
  384. continue;
  385. /* Endpoint with matching usertokenpolicy found */
  386. tokenFound = true;
  387. UA_UserTokenPolicy_deleteMembers(&client->token);
  388. UA_UserTokenPolicy_copy(userToken, &client->token);
  389. break;
  390. }
  391. }
  392. UA_Array_delete(endpointArray, endpointArraySize,
  393. &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
  394. if(!endpointFound) {
  395. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
  396. "No suitable endpoint found");
  397. retval = UA_STATUSCODE_BADINTERNALERROR;
  398. } else if(!tokenFound) {
  399. UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
  400. "No suitable UserTokenPolicy found for the possible endpoints");
  401. retval = UA_STATUSCODE_BADINTERNALERROR;
  402. }
  403. return retval;
  404. }
  405. static UA_StatusCode
  406. createSession(UA_Client *client) {
  407. UA_CreateSessionRequest request;
  408. UA_CreateSessionRequest_init(&request);
  409. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  410. if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
  411. client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
  412. if(client->channel.localNonce.length != UA_SESSION_LOCALNONCELENGTH) {
  413. UA_ByteString_deleteMembers(&client->channel.localNonce);
  414. retval = UA_ByteString_allocBuffer(&client->channel.localNonce,
  415. UA_SESSION_LOCALNONCELENGTH);
  416. if(retval != UA_STATUSCODE_GOOD)
  417. return retval;
  418. }
  419. retval = client->channel.securityPolicy->symmetricModule.
  420. generateNonce(client->channel.securityPolicy, &client->channel.localNonce);
  421. if(retval != UA_STATUSCODE_GOOD)
  422. return retval;
  423. }
  424. request.requestHeader.timestamp = UA_DateTime_now();
  425. request.requestHeader.timeoutHint = 10000;
  426. UA_ByteString_copy(&client->channel.localNonce, &request.clientNonce);
  427. request.requestedSessionTimeout = 1200000;
  428. request.maxResponseMessageSize = UA_INT32_MAX;
  429. UA_String_copy(&client->endpointUrl, &request.endpointUrl);
  430. if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
  431. client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
  432. UA_ByteString_copy(&client->channel.securityPolicy->localCertificate,
  433. &request.clientCertificate);
  434. }
  435. UA_CreateSessionResponse response;
  436. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
  437. &response, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
  438. if(response.responseHeader.serviceResult == UA_STATUSCODE_GOOD &&
  439. (client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
  440. client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)) {
  441. UA_ByteString_deleteMembers(&client->channel.remoteNonce);
  442. UA_ByteString_copy(&response.serverNonce, &client->channel.remoteNonce);
  443. if(!UA_ByteString_equal(&response.serverCertificate,
  444. &client->channel.remoteCertificate)) {
  445. return UA_STATUSCODE_BADCERTIFICATEINVALID;
  446. }
  447. /* Verify the client signature */
  448. retval = checkClientSignature(&client->channel, &response);
  449. if(retval != UA_STATUSCODE_GOOD)
  450. return retval;
  451. }
  452. UA_NodeId_copy(&response.authenticationToken, &client->authenticationToken);
  453. retval = response.responseHeader.serviceResult;
  454. UA_CreateSessionRequest_deleteMembers(&request);
  455. UA_CreateSessionResponse_deleteMembers(&response);
  456. return retval;
  457. }
  458. UA_StatusCode
  459. UA_Client_connectInternal(UA_Client *client, const char *endpointUrl,
  460. UA_Boolean endpointsHandshake, UA_Boolean createNewSession) {
  461. if(client->state >= UA_CLIENTSTATE_CONNECTED)
  462. return UA_STATUSCODE_GOOD;
  463. UA_ChannelSecurityToken_init(&client->channel.securityToken);
  464. client->channel.state = UA_SECURECHANNELSTATE_FRESH;
  465. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  466. client->connection =
  467. client->config.connectionFunc(client->config.localConnectionConfig,
  468. endpointUrl, client->config.timeout,
  469. client->config.logger);
  470. if(client->connection.state != UA_CONNECTION_OPENING) {
  471. retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
  472. goto cleanup;
  473. }
  474. UA_String_deleteMembers(&client->endpointUrl);
  475. client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
  476. if(!client->endpointUrl.data) {
  477. retval = UA_STATUSCODE_BADOUTOFMEMORY;
  478. goto cleanup;
  479. }
  480. /* Local nonce set and generate sym keys */
  481. retval |= UA_SecureChannel_generateLocalNonce(&client->channel);
  482. if(retval != UA_STATUSCODE_GOOD)
  483. return retval;
  484. /* Open a TCP connection */
  485. client->connection.localConf = client->config.localConnectionConfig;
  486. retval = HelAckHandshake(client);
  487. if(retval != UA_STATUSCODE_GOOD)
  488. goto cleanup;
  489. setClientState(client, UA_CLIENTSTATE_CONNECTED);
  490. /* Open a SecureChannel. TODO: Select with endpoint */
  491. client->channel.connection = &client->connection;
  492. retval = openSecureChannel(client, false);
  493. if(retval != UA_STATUSCODE_GOOD)
  494. goto cleanup;
  495. setClientState(client, UA_CLIENTSTATE_SECURECHANNEL);
  496. /* Delete async service. TODO: Move this from connect to the disconnect/cleanup phase */
  497. UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSHUTDOWN);
  498. #ifdef UA_ENABLE_SUBSCRIPTIONS
  499. client->currentlyOutStandingPublishRequests = 0;
  500. #endif
  501. // TODO: actually, reactivate an existing session is working, but currently republish is not implemented
  502. // This option is disabled until we have a good implementation of the subscription recovery.
  503. #ifdef UA_SESSION_RECOVERY
  504. /* Try to activate an existing Session for this SecureChannel */
  505. if((!UA_NodeId_equal(&client->authenticationToken, &UA_NODEID_NULL)) && (createNewSession)) {
  506. retval = activateSession(client);
  507. if(retval == UA_STATUSCODE_BADSESSIONIDINVALID) {
  508. /* Could not recover an old session. Remove authenticationToken */
  509. UA_NodeId_deleteMembers(&client->authenticationToken);
  510. } else {
  511. if(retval != UA_STATUSCODE_GOOD)
  512. goto cleanup;
  513. setClientState(client, UA_CLIENTSTATE_SESSION_RENEWED);
  514. return retval;
  515. }
  516. } else {
  517. UA_NodeId_deleteMembers(&client->authenticationToken);
  518. }
  519. #else
  520. UA_NodeId_deleteMembers(&client->authenticationToken);
  521. #endif /* UA_SESSION_RECOVERY */
  522. /* Generate new local and remote key */
  523. retval |= UA_SecureChannel_generateNewKeys(&client->channel);
  524. if(retval != UA_STATUSCODE_GOOD)
  525. return retval;
  526. /* Get Endpoints */
  527. if(endpointsHandshake) {
  528. retval = getEndpoints(client);
  529. if(retval != UA_STATUSCODE_GOOD)
  530. goto cleanup;
  531. }
  532. /* Create the Session for this SecureChannel */
  533. if(createNewSession) {
  534. retval = createSession(client);
  535. if(retval != UA_STATUSCODE_GOOD)
  536. goto cleanup;
  537. #ifdef UA_ENABLE_SUBSCRIPTIONS
  538. /* A new session has been created. We need to clean up the subscriptions */
  539. UA_Client_Subscriptions_clean(client);
  540. #endif
  541. retval = activateSession(client);
  542. if(retval != UA_STATUSCODE_GOOD)
  543. goto cleanup;
  544. setClientState(client, UA_CLIENTSTATE_SESSION);
  545. }
  546. return retval;
  547. cleanup:
  548. UA_Client_close(client);
  549. return retval;
  550. }
  551. UA_StatusCode
  552. UA_Client_connect(UA_Client *client, const char *endpointUrl) {
  553. return UA_Client_connectInternal(client, endpointUrl, UA_TRUE, UA_TRUE);
  554. }
  555. UA_StatusCode
  556. UA_Client_connect_noSession(UA_Client *client, const char *endpointUrl) {
  557. return UA_Client_connectInternal(client, endpointUrl, UA_TRUE, UA_FALSE);
  558. }
  559. UA_StatusCode
  560. UA_Client_connect_username(UA_Client *client, const char *endpointUrl,
  561. const char *username, const char *password) {
  562. client->authenticationMethod = UA_CLIENTAUTHENTICATION_USERNAME;
  563. client->username = UA_STRING_ALLOC(username);
  564. client->password = UA_STRING_ALLOC(password);
  565. return UA_Client_connect(client, endpointUrl);
  566. }
  567. UA_StatusCode
  568. UA_Client_manuallyRenewSecureChannel(UA_Client *client) {
  569. UA_StatusCode retval = openSecureChannel(client, true);
  570. if(retval != UA_STATUSCODE_GOOD)
  571. UA_Client_close(client);
  572. return retval;
  573. }
  574. /************************/
  575. /* Close the Connection */
  576. /************************/
  577. static void
  578. sendCloseSession(UA_Client *client) {
  579. UA_CloseSessionRequest request;
  580. UA_CloseSessionRequest_init(&request);
  581. request.requestHeader.timestamp = UA_DateTime_now();
  582. request.requestHeader.timeoutHint = 10000;
  583. request.deleteSubscriptions = true;
  584. UA_CloseSessionResponse response;
  585. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
  586. &response, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
  587. UA_CloseSessionRequest_deleteMembers(&request);
  588. UA_CloseSessionResponse_deleteMembers(&response);
  589. }
  590. static void
  591. sendCloseSecureChannel(UA_Client *client) {
  592. UA_SecureChannel *channel = &client->channel;
  593. UA_CloseSecureChannelRequest request;
  594. UA_CloseSecureChannelRequest_init(&request);
  595. request.requestHeader.requestHandle = ++client->requestHandle;
  596. request.requestHeader.timestamp = UA_DateTime_now();
  597. request.requestHeader.timeoutHint = 10000;
  598. request.requestHeader.authenticationToken = client->authenticationToken;
  599. UA_SecureChannel_sendSymmetricMessage(channel, ++client->requestId,
  600. UA_MESSAGETYPE_CLO, &request,
  601. &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
  602. UA_CloseSecureChannelRequest_deleteMembers(&request);
  603. UA_SecureChannel_deleteMembersCleanup(&client->channel);
  604. }
  605. UA_StatusCode
  606. UA_Client_disconnect(UA_Client *client) {
  607. /* Is a session established? */
  608. if(client->state >= UA_CLIENTSTATE_SESSION) {
  609. client->state = UA_CLIENTSTATE_SECURECHANNEL;
  610. sendCloseSession(client);
  611. }
  612. UA_NodeId_deleteMembers(&client->authenticationToken);
  613. client->requestHandle = 0;
  614. /* Is a secure channel established? */
  615. if(client->state >= UA_CLIENTSTATE_SECURECHANNEL) {
  616. client->state = UA_CLIENTSTATE_CONNECTED;
  617. sendCloseSecureChannel(client);
  618. }
  619. /* Close the TCP connection */
  620. if(client->connection.state != UA_CONNECTION_CLOSED)
  621. client->connection.close(&client->connection);
  622. #ifdef UA_ENABLE_SUBSCRIPTIONS
  623. // TODO REMOVE WHEN UA_SESSION_RECOVERY IS READY
  624. /* We need to clean up the subscriptions */
  625. UA_Client_Subscriptions_clean(client);
  626. #endif
  627. setClientState(client, UA_CLIENTSTATE_DISCONNECTED);
  628. return UA_STATUSCODE_GOOD;
  629. }
  630. UA_StatusCode
  631. UA_Client_close(UA_Client *client) {
  632. client->requestHandle = 0;
  633. if(client->state >= UA_CLIENTSTATE_SECURECHANNEL)
  634. UA_SecureChannel_deleteMembersCleanup(&client->channel);
  635. /* Close the TCP connection */
  636. if(client->connection.state != UA_CONNECTION_CLOSED)
  637. client->connection.close(&client->connection);
  638. #ifdef UA_ENABLE_SUBSCRIPTIONS
  639. // TODO REMOVE WHEN UA_SESSION_RECOVERY IS READY
  640. /* We need to clean up the subscriptions */
  641. UA_Client_Subscriptions_clean(client);
  642. #endif
  643. setClientState(client, UA_CLIENTSTATE_DISCONNECTED);
  644. return UA_STATUSCODE_GOOD;
  645. }