123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- #include "ua_util.h"
- #include "ua_securechannel.h"
- #include "ua_session.h"
- #include "ua_types_encoding_binary.h"
- #include "ua_transport_generated_encoding_binary.h"
- void UA_SecureChannel_init(UA_SecureChannel *channel) {
- UA_MessageSecurityMode_init(&channel->securityMode);
- UA_ChannelSecurityToken_init(&channel->securityToken);
- UA_ChannelSecurityToken_init(&channel->nextSecurityToken);
- UA_AsymmetricAlgorithmSecurityHeader_init(&channel->clientAsymAlgSettings);
- UA_AsymmetricAlgorithmSecurityHeader_init(&channel->serverAsymAlgSettings);
- UA_ByteString_init(&channel->clientNonce);
- UA_ByteString_init(&channel->serverNonce);
- channel->sequenceNumber = 0;
- channel->connection = UA_NULL;
- LIST_INIT(&channel->sessions);
- }
- void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel) {
- UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->serverAsymAlgSettings);
- UA_ByteString_deleteMembers(&channel->serverNonce);
- UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->clientAsymAlgSettings);
- UA_ByteString_deleteMembers(&channel->clientNonce);
- UA_ChannelSecurityToken_deleteMembers(&channel->securityToken); //FIXME: not really needed
- UA_ChannelSecurityToken_deleteMembers(&channel->nextSecurityToken); //FIXME: not really needed
- UA_Connection *c = channel->connection;
- if(c) {
- UA_Connection_detachSecureChannel(c);
- if(c->close)
- c->close(c);
- }
- /* just remove the pointers and free the linked list (not the sessions) */
- struct SessionEntry *se;
- while((se = LIST_FIRST(&channel->sessions))) {
- UA_SecureChannel_detachSession(channel, se->session); /* the se is deleted inside */
- }
- }
- //TODO implement real nonce generator - DUMMY function
- UA_StatusCode UA_SecureChannel_generateNonce(UA_ByteString *nonce) {
- if(!(nonce->data = UA_malloc(1)))
- return UA_STATUSCODE_BADOUTOFMEMORY;
- nonce->length = 1;
- nonce->data[0] = 'a';
- return UA_STATUSCODE_GOOD;
- }
- void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session) {
- struct SessionEntry *se = UA_malloc(sizeof(struct SessionEntry));
- if(!se)
- return;
- se->session = session;
- #ifdef UA_MULTITHREADING
- if(uatomic_cmpxchg(&session->channel, UA_NULL, channel) != UA_NULL) {
- UA_free(se);
- return;
- }
- #else
- if(session->channel != UA_NULL) {
- UA_free(se);
- return;
- }
- session->channel = channel;
- #endif
- LIST_INSERT_HEAD(&channel->sessions, se, pointers);
- }
- void UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session) {
- if(session)
- session->channel = UA_NULL;
- struct SessionEntry *se;
- LIST_FOREACH(se, &channel->sessions, pointers) {
- if(se->session != session)
- continue;
- LIST_REMOVE(se, pointers);
- UA_free(se);
- break;
- }
- }
- UA_Session * UA_SecureChannel_getSession(UA_SecureChannel *channel, UA_NodeId *token) {
- struct SessionEntry *se;
- LIST_FOREACH(se, &channel->sessions, pointers) {
- if(UA_NodeId_equal(&se->session->authenticationToken, token))
- break;
- }
- if(!se)
- return UA_NULL;
- return se->session;
- }
- void UA_SecureChannel_revolveTokens(UA_SecureChannel *channel){
- if(channel->nextSecurityToken.tokenId==0) //no security token issued
- return;
- //FIXME: not thread-safe
- //swap tokens
- memcpy(&channel->securityToken, &channel->nextSecurityToken, sizeof(UA_ChannelSecurityToken));
- UA_ChannelSecurityToken_init(&channel->nextSecurityToken);
- }
- UA_StatusCode UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
- const void *content,
- const UA_DataType *contentType) {
- UA_Connection *connection = channel->connection;
- if(!connection)
- return UA_STATUSCODE_BADINTERNALERROR;
- UA_NodeId typeId = contentType->typeId;
- if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
- return UA_STATUSCODE_BADINTERNALERROR;
- typeId.identifier.numeric += UA_ENCODINGOFFSET_BINARY;
- UA_SecureConversationMessageHeader respHeader;
- respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_MSGF;
- respHeader.messageHeader.messageSize = 0;
- respHeader.secureChannelId = channel->securityToken.channelId;
- UA_SymmetricAlgorithmSecurityHeader symSecHeader;
- symSecHeader.tokenId = channel->securityToken.tokenId;
- UA_SequenceHeader seqHeader;
- seqHeader.requestId = requestId;
- UA_ByteString message;
- UA_StatusCode retval = connection->getBuffer(connection, &message);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
- size_t messagePos = 24; // after the headers
- retval |= UA_NodeId_encodeBinary(&typeId, &message, &messagePos);
- retval |= UA_encodeBinary(content, contentType, &message, &messagePos);
- if(retval != UA_STATUSCODE_GOOD) {
- connection->releaseBuffer(connection, &message);
- return retval;
- }
- /* now write the header with the size */
- respHeader.messageHeader.messageSize = messagePos;
- #ifndef UA_MULTITHREADING
- seqHeader.sequenceNumber = ++channel->sequenceNumber;
- #else
- seqHeader.sequenceNumber = uatomic_add_return(&channel->sequenceNumber, 1);
- #endif
- messagePos = 0;
- UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &message, &messagePos);
- UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symSecHeader, &message, &messagePos);
- UA_SequenceHeader_encodeBinary(&seqHeader, &message, &messagePos);
-
- retval = connection->write(connection, &message, respHeader.messageHeader.messageSize);
- if(retval != UA_STATUSCODE_GOOD)
- connection->releaseBuffer(connection, &message);
- return retval;
- }
|