ua_client_connect.c 31 KB

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