Procházet zdrojové kódy

move session definition into server

This removes details of the server's Session implementation from the
SecureChannel code. This was unwanted as the SecureChannel is also used
by the client.
Julius Pfrommer před 6 roky
rodič
revize
5c27c73a4b

+ 2 - 2
CMakeLists.txt

@@ -331,8 +331,8 @@ set(internal_headers ${PROJECT_SOURCE_DIR}/deps/queue.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated_encoding_binary.h
                      ${PROJECT_SOURCE_DIR}/src/ua_connection_internal.h
                      ${PROJECT_SOURCE_DIR}/src/ua_securechannel.h
-                     ${PROJECT_SOURCE_DIR}/src/ua_session.h
                      ${PROJECT_SOURCE_DIR}/src/ua_timer.h
+                     ${PROJECT_SOURCE_DIR}/src/server/ua_session.h
                      ${PROJECT_SOURCE_DIR}/src/server/ua_subscription.h
                      ${PROJECT_SOURCE_DIR}/src/server/ua_session_manager.h
                      ${PROJECT_SOURCE_DIR}/src/server/ua_securechannel_manager.h
@@ -349,9 +349,9 @@ set(lib_sources ${PROJECT_SOURCE_DIR}/src/ua_types.c
                 ${PROJECT_BINARY_DIR}/src_generated/ua_statuscode_descriptions.c
                 ${PROJECT_SOURCE_DIR}/src/ua_util.c
                 ${PROJECT_SOURCE_DIR}/src/ua_timer.c
-                ${PROJECT_SOURCE_DIR}/src/ua_session.c
                 ${PROJECT_SOURCE_DIR}/src/ua_connection.c
                 ${PROJECT_SOURCE_DIR}/src/ua_securechannel.c
+                ${PROJECT_SOURCE_DIR}/src/server/ua_session.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_nodes.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_server.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_server_ns0.c

+ 4 - 4
src/server/ua_server_binary.c

@@ -447,7 +447,7 @@ processMSG(UA_Server *server, UA_SecureChannel *channel,
     #endif
 
     /* Find the matching session */
-    session = UA_SecureChannel_getSession(channel, &requestHeader->authenticationToken);
+    session = (UA_Session*)UA_SecureChannel_getSession(channel, &requestHeader->authenticationToken);
     if(!session && !UA_NodeId_isNull(&requestHeader->authenticationToken))
         session = UA_SessionManager_getSessionByToken(&server->sessionManager,
                                                       &requestHeader->authenticationToken);
@@ -481,7 +481,7 @@ processMSG(UA_Server *server, UA_SecureChannel *channel,
 
         UA_Session_init(&anonymousSession);
         anonymousSession.sessionId = UA_NODEID_GUID(0, UA_GUID_NULL);
-        anonymousSession.channel = channel;
+        anonymousSession.header.channel = channel;
         session = &anonymousSession;
     }
 
@@ -491,14 +491,14 @@ processMSG(UA_Server *server, UA_SecureChannel *channel,
                                "Calling service %i on a non-activated session",
                                requestType->binaryEncodingId);
         UA_SessionManager_removeSession(&server->sessionManager,
-                                        &session->authenticationToken);
+                                        &session->header.authenticationToken);
         UA_deleteMembers(request, requestType);
         return sendServiceFault(channel, msg, requestPos, responseType,
                                 requestId, UA_STATUSCODE_BADSESSIONNOTACTIVATED);
     }
 
     /* The session is bound to another channel */
-    if(session != &anonymousSession && session->channel != channel) {
+    if(session != &anonymousSession && session->header.channel != channel) {
         UA_LOG_WARNING_CHANNEL(server->config.logger, channel,
                                "Client tries to use a Session that is not "
                                "bound to this SecureChannel");

+ 13 - 10
src/server/ua_services_session.c

@@ -20,13 +20,15 @@ nonceAndSignCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
     const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
     UA_SignatureData *signatureData = &response->serverSignature;
 
+    const UA_NodeId *authenticationToken = &session->header.authenticationToken;
+
     /* Generate Nonce
      * FIXME: remove magic number??? */
     UA_StatusCode retval = UA_SecureChannel_generateNonce(channel, 32, &response->serverNonce);
     UA_ByteString_deleteMembers(&session->serverNonce);
     retval |= UA_ByteString_copy(&response->serverNonce, &session->serverNonce);
     if(retval != UA_STATUSCODE_GOOD) {
-        UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
+        UA_SessionManager_removeSession(&server->sessionManager, authenticationToken);
         return retval;
     }
 
@@ -35,7 +37,7 @@ nonceAndSignCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
 
     retval |= UA_ByteString_allocBuffer(&signatureData->signature, signatureSize);
     if(retval != UA_STATUSCODE_GOOD) {
-        UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
+        UA_SessionManager_removeSession(&server->sessionManager, authenticationToken);
         return retval;
     }
 
@@ -45,7 +47,7 @@ nonceAndSignCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
                                         request->clientNonce.length);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_SignatureData_deleteMembers(signatureData);
-        UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
+        UA_SessionManager_removeSession(&server->sessionManager, authenticationToken);
         return retval;
     }
 
@@ -61,7 +63,7 @@ nonceAndSignCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
     UA_ByteString_deleteMembers(&dataToSign);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_SignatureData_deleteMembers(signatureData);
-        UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
+        UA_SessionManager_removeSession(&server->sessionManager, authenticationToken);
     }
     return retval;
 }
@@ -150,7 +152,7 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
     /* Prepare the response */
     response->sessionId = newSession->sessionId;
     response->revisedSessionTimeout = (UA_Double)newSession->timeout;
-    response->authenticationToken = newSession->authenticationToken;
+    response->authenticationToken = newSession->header.authenticationToken;
     response->responseHeader.serviceResult =
         UA_String_copy(&request->sessionName, &newSession->sessionName);
 
@@ -165,7 +167,8 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
 
     /* Failure -> remove the session */
     if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
-        UA_SessionManager_removeSession(&server->sessionManager, &newSession->authenticationToken);
+        UA_SessionManager_removeSession(&server->sessionManager,
+                                        &newSession->header.authenticationToken);
         return;
     }
 
@@ -253,14 +256,14 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
         return;
 
     /* Detach the old SecureChannel */
-    if(session->channel && session->channel != channel) {
+    if(session->header.channel && session->header.channel != channel) {
         UA_LOG_INFO_SESSION(server->config.logger, session,
                             "ActivateSession: Detach from old channel");
-        UA_SecureChannel_detachSession(session->channel, session);
+        UA_Session_detachFromSecureChannel(session);
     }
 
     /* Attach to the SecureChannel and activate */
-    UA_SecureChannel_attachSession(channel, session);
+    UA_Session_attachToSecureChannel(session, channel);
     session->activated = true;
     UA_Session_updateLifetime(session);
     UA_LOG_INFO_SESSION(server->config.logger, session,
@@ -278,5 +281,5 @@ Service_CloseSession(UA_Server *server, UA_Session *session,
                                               session->sessionHandle);
     response->responseHeader.serviceResult =
         UA_SessionManager_removeSession(&server->sessionManager,
-                                        &session->authenticationToken);
+                                        &session->header.authenticationToken);
 }

+ 6 - 6
src/server/ua_services_subscription.c

@@ -451,7 +451,7 @@ Service_Publish(UA_Server *server, UA_Session *session,
 
     /* Return an error if the session has no subscription */
     if(LIST_EMPTY(&session->serverSubscriptions)) {
-        subscriptionSendError(session->channel, request->requestHeader.requestHandle,
+        subscriptionSendError(session->header.channel, request->requestHeader.requestHandle,
                               requestId, UA_STATUSCODE_BADNOSUBSCRIPTION);
         return;
     }
@@ -462,17 +462,17 @@ Service_Publish(UA_Server *server, UA_Session *session,
     if((server->config.maxPublishReqPerSession != 0 ) &&
        (UA_Session_getNumPublishReq(session) >= server->config.maxPublishReqPerSession)){
         if(!UA_Subscription_reachedPublishReqLimit(server,session)) {
-            subscriptionSendError(session->channel, requestId,
+            subscriptionSendError(session->header.channel, requestId,
                                   request->requestHeader.requestHandle,
                                   UA_STATUSCODE_BADINTERNALERROR);
             return;
         }
     }
 
-    UA_PublishResponseEntry *entry =
-        (UA_PublishResponseEntry*)UA_malloc(sizeof(UA_PublishResponseEntry));
+    UA_PublishResponseEntry *entry = (UA_PublishResponseEntry*)
+        UA_malloc(sizeof(UA_PublishResponseEntry));
     if(!entry) {
-        subscriptionSendError(session->channel, requestId,
+        subscriptionSendError(session->header.channel, requestId,
                               request->requestHeader.requestHandle,
                               UA_STATUSCODE_BADOUTOFMEMORY);
         return;
@@ -489,7 +489,7 @@ Service_Publish(UA_Server *server, UA_Session *session,
                          &UA_TYPES[UA_TYPES_STATUSCODE]);
         if(!response->results) {
             UA_free(entry);
-            subscriptionSendError(session->channel, requestId,
+            subscriptionSendError(session->header.channel, requestId,
                                   request->requestHeader.requestHandle,
                                   UA_STATUSCODE_BADOUTOFMEMORY);
             return;

+ 18 - 24
src/ua_session.c

@@ -3,13 +3,14 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ua_session.h"
-#include "ua_types_generated_handling.h"
-#include "ua_util.h"
 #ifdef UA_ENABLE_SUBSCRIPTIONS
 #include "server/ua_subscription.h"
 #endif
 
 UA_Session adminSession = {
+    {{NULL, NULL}, /* .pointers */
+     {0,UA_NODEIDTYPE_NUMERIC,{1}}, /* .authenticationToken */
+     NULL,}, /* .channel */
     {{0, NULL},{0, NULL},
      {{0, NULL},{0, NULL}},
      UA_APPLICATIONTYPE_CLIENT,
@@ -18,14 +19,12 @@ UA_Session adminSession = {
     {sizeof("Administrator Session")-1, (UA_Byte*)"Administrator Session"}, /* .sessionName */
     false, /* .activated */
     NULL, /* .sessionHandle */
-    {0,UA_NODEIDTYPE_NUMERIC,{1}}, /* .authenticationToken */
     {0,UA_NODEIDTYPE_NUMERIC,{1}}, /* .sessionId */
     UA_UINT32_MAX, /* .maxRequestMessageSize */
     UA_UINT32_MAX, /* .maxResponseMessageSize */
     (UA_Double)UA_INT64_MAX, /* .timeout */
     UA_INT64_MAX, /* .validTill */
     {0, NULL},
-    NULL, /* .channel */
     UA_MAXCONTINUATIONPOINTS, /* .availableContinuationPoints */
     {NULL}, /* .continuationPoints */
 #ifdef UA_ENABLE_SUBSCRIPTIONS
@@ -39,32 +38,17 @@ UA_Session adminSession = {
 };
 
 void UA_Session_init(UA_Session *session) {
-    UA_ApplicationDescription_init(&session->clientDescription);
-    session->activated = false;
-    UA_NodeId_init(&session->authenticationToken);
-    UA_NodeId_init(&session->sessionId);
-    UA_String_init(&session->sessionName);
-    UA_ByteString_init(&session->serverNonce);
-    session->maxRequestMessageSize  = 0;
-    session->maxResponseMessageSize = 0;
-    session->timeout = 0;
-    UA_DateTime_init(&session->validTill);
-    session->channel = NULL;
+    memset(session, 0, sizeof(UA_Session));
     session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
-    LIST_INIT(&session->continuationPoints);
 #ifdef UA_ENABLE_SUBSCRIPTIONS
-    LIST_INIT(&session->serverSubscriptions);
-    session->lastSubscriptionID = 0;
-    session->lastSeenSubscriptionID = 0;
     SIMPLEQ_INIT(&session->responseQueue);
-    session->numSubscriptions = 0;
-    session->numPublishReq = 0;
 #endif
 }
 
 void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server* server) {
+    UA_Session_detachFromSecureChannel(session);
     UA_ApplicationDescription_deleteMembers(&session->clientDescription);
-    UA_NodeId_deleteMembers(&session->authenticationToken);
+    UA_NodeId_deleteMembers(&session->header.authenticationToken);
     UA_NodeId_deleteMembers(&session->sessionId);
     UA_String_deleteMembers(&session->sessionName);
     UA_ByteString_deleteMembers(&session->serverNonce);
@@ -75,8 +59,6 @@ void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server* server) {
         UA_BrowseDescription_deleteMembers(&cp->browseDescription);
         UA_free(cp);
     }
-    if(session->channel)
-        UA_SecureChannel_detachSession(session->channel, session);
 #ifdef UA_ENABLE_SUBSCRIPTIONS
     UA_Subscription *currents, *temps;
     LIST_FOREACH_SAFE(currents, &session->serverSubscriptions, listEntry, temps) {
@@ -93,6 +75,18 @@ void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server* server) {
 #endif
 }
 
+void UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel) {
+    LIST_INSERT_HEAD(&channel->sessions, &session->header, pointers);
+    session->header.channel = channel;
+}
+
+void UA_Session_detachFromSecureChannel(UA_Session *session) {
+    if(!session->header.channel)
+        return;
+    session->header.channel = NULL;
+    LIST_REMOVE(&session->header, pointers);
+}
+
 void UA_Session_updateLifetime(UA_Session *session) {
     session->validTill = UA_DateTime_nowMonotonic() +
         (UA_DateTime)(session->timeout * UA_DATETIME_MSEC);

+ 26 - 20
src/ua_session.h

@@ -10,10 +10,7 @@ extern "C" {
 #endif
 
 #include "queue.h"
-#include "ua_types.h"
 #include "ua_securechannel.h"
-#include "ua_server.h"
-#include "ua_util.h"
 
 #define UA_MAXCONTINUATIONPOINTS 5
 
@@ -39,19 +36,18 @@ typedef struct UA_PublishResponseEntry {
 } UA_PublishResponseEntry;
 #endif
 
-struct UA_Session {
+typedef struct {
+    UA_SessionHeader  header;
     UA_ApplicationDescription clientDescription;
     UA_String         sessionName;
     UA_Boolean        activated;
     void             *sessionHandle; // pointer assigned in userland-callback
-    UA_NodeId         authenticationToken;
     UA_NodeId         sessionId;
     UA_UInt32         maxRequestMessageSize;
     UA_UInt32         maxResponseMessageSize;
     UA_Double         timeout; // [ms]
     UA_DateTime       validTill;
     UA_ByteString     serverNonce;
-    UA_SecureChannel *channel;
     UA_UInt16 availableContinuationPoints;
     LIST_HEAD(ContinuationPointList, ContinuationPointEntry) continuationPoints;
 #ifdef UA_ENABLE_SUBSCRIPTIONS
@@ -62,23 +58,33 @@ struct UA_Session {
     UA_UInt32        numSubscriptions;
     UA_UInt32        numPublishReq;
 #endif
-};
+} UA_Session;
 
 /* Local access to the services (for startup and maintenance) uses this Session
  * with all possible access rights (Session ID: 1) */
 extern UA_Session adminSession;
 
+/**
+ * Session Lifecycle
+ * ----------------- */
+
 void UA_Session_init(UA_Session *session);
 void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server *server);
+void UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel);
+void UA_Session_detachFromSecureChannel(UA_Session *session);
 
 /* If any activity on a session happens, the timeout is extended */
 void UA_Session_updateLifetime(UA_Session *session);
 
+/**
+ * Subscription handling
+ * --------------------- */
+
 #ifdef UA_ENABLE_SUBSCRIPTIONS
 void UA_Session_addSubscription(UA_Session *session, UA_Subscription *newSubscription);
 
 UA_UInt32
-UA_Session_getNumSubscriptions( UA_Session *session );
+UA_Session_getNumSubscriptions(UA_Session *session );
 
 UA_Subscription *
 UA_Session_getSubscriptionByID(UA_Session *session, UA_UInt32 subscriptionID);
@@ -115,8 +121,8 @@ UA_Session_addPublishReq(UA_Session *session, UA_PublishResponseEntry* entry);
 #define UA_LOG_TRACE_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...)        \
     UA_LOG_TRACE(LOGGER, UA_LOGCATEGORY_SESSION,                        \
                  "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
-                 ((SESSION)->channel ? ((SESSION)->channel->connection ? (SESSION)->channel->connection->sockfd : 0) : 0), \
-                 ((SESSION)->channel ? (SESSION)->channel->securityToken.channelId : 0), \
+                 ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+                 ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
                  UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
 
 #define UA_LOG_TRACE_SESSION(LOGGER, SESSION, ...)                      \
@@ -125,8 +131,8 @@ UA_Session_addPublishReq(UA_Session *session, UA_PublishResponseEntry* entry);
 #define UA_LOG_DEBUG_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...)        \
     UA_LOG_DEBUG(LOGGER, UA_LOGCATEGORY_SESSION,                        \
                  "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
-                 ((SESSION)->channel ? ((SESSION)->channel->connection ? (SESSION)->channel->connection->sockfd : 0) : 0), \
-                 ((SESSION)->channel ? (SESSION)->channel->securityToken.channelId : 0), \
+                 ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+                 ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
                  UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
 
 #define UA_LOG_DEBUG_SESSION(LOGGER, SESSION, ...)                      \
@@ -135,8 +141,8 @@ UA_Session_addPublishReq(UA_Session *session, UA_PublishResponseEntry* entry);
 #define UA_LOG_INFO_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...)        \
     UA_LOG_INFO(LOGGER, UA_LOGCATEGORY_SESSION,                        \
                  "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
-                 ((SESSION)->channel ? ((SESSION)->channel->connection ? (SESSION)->channel->connection->sockfd : 0) : 0), \
-                 ((SESSION)->channel ? (SESSION)->channel->securityToken.channelId : 0), \
+                 ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+                 ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
                  UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
 
 #define UA_LOG_INFO_SESSION(LOGGER, SESSION, ...)                      \
@@ -145,8 +151,8 @@ UA_Session_addPublishReq(UA_Session *session, UA_PublishResponseEntry* entry);
 #define UA_LOG_WARNING_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...)        \
     UA_LOG_WARNING(LOGGER, UA_LOGCATEGORY_SESSION,                        \
                  "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
-                 ((SESSION)->channel ? ((SESSION)->channel->connection ? (SESSION)->channel->connection->sockfd : 0) : 0), \
-                 ((SESSION)->channel ? (SESSION)->channel->securityToken.channelId : 0), \
+                 ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+                 ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
                  UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
 
 #define UA_LOG_WARNING_SESSION(LOGGER, SESSION, ...)                      \
@@ -155,8 +161,8 @@ UA_Session_addPublishReq(UA_Session *session, UA_PublishResponseEntry* entry);
 #define UA_LOG_ERROR_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...)        \
     UA_LOG_ERROR(LOGGER, UA_LOGCATEGORY_SESSION,                        \
                  "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
-                 ((SESSION)->channel ? ((SESSION)->channel->connection ? (SESSION)->channel->connection->sockfd : 0) : 0), \
-                 ((SESSION)->channel ? (SESSION)->channel->securityToken.channelId : 0), \
+                 ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+                 ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
                  UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
 
 #define UA_LOG_ERROR_SESSION(LOGGER, SESSION, ...)                      \
@@ -165,8 +171,8 @@ UA_Session_addPublishReq(UA_Session *session, UA_PublishResponseEntry* entry);
 #define UA_LOG_FATAL_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...)        \
     UA_LOG_FATAL(LOGGER, UA_LOGCATEGORY_SESSION,                        \
                  "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
-                 ((SESSION)->channel ? ((SESSION)->channel->connection ? (SESSION)->channel->connection->sockfd : 0) : 0), \
-                 ((SESSION)->channel ? (SESSION)->channel->securityToken.channelId : 0), \
+                 ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+                 ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
                  UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
 
 #define UA_LOG_FATAL_SESSION(LOGGER, SESSION, ...)                      \

+ 3 - 3
src/server/ua_session_manager.c

@@ -72,7 +72,7 @@ UA_SessionManager_getSessionByToken(UA_SessionManager *sm, const UA_NodeId *toke
     session_list_entry *current = NULL;
     LIST_FOREACH(current, &sm->sessions, pointers) {
         /* Token does not match */
-        if(!UA_NodeId_equal(&current->session.authenticationToken, token))
+        if(!UA_NodeId_equal(&current->session.header.authenticationToken, token))
             continue;
 
         /* Session has timed out */
@@ -133,7 +133,7 @@ UA_SessionManager_createSession(UA_SessionManager *sm, UA_SecureChannel *channel
     UA_atomic_add(&sm->currentSessionCount, 1);
     UA_Session_init(&newentry->session);
     newentry->session.sessionId = UA_NODEID_GUID(1, UA_Guid_random());
-    newentry->session.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
+    newentry->session.header.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
 
     if(request->requestedSessionTimeout <= sm->server->config.maxSessionTimeout &&
        request->requestedSessionTimeout > 0)
@@ -151,7 +151,7 @@ UA_StatusCode
 UA_SessionManager_removeSession(UA_SessionManager *sm, const UA_NodeId *token) {
     session_list_entry *current;
     LIST_FOREACH(current, &sm->sessions, pointers) {
-        if(UA_NodeId_equal(&current->session.authenticationToken, token))
+        if(UA_NodeId_equal(&current->session.header.authenticationToken, token))
             break;
     }
     if(!current)

+ 4 - 4
src/server/ua_subscription.c

@@ -268,7 +268,7 @@ UA_Subscription_publishCallback(UA_Server *server, UA_Subscription *sub) {
     }
 
     /* Check if the securechannel is valid */
-    UA_SecureChannel *channel = sub->session->channel;
+    UA_SecureChannel *channel = sub->session->header.channel;
     if(!channel)
         return;
 
@@ -367,7 +367,7 @@ UA_Subscription_publishCallback(UA_Server *server, UA_Subscription *sub) {
                          "Subscription %u | Sending out a publish response "
                          "with %u notifications", sub->subscriptionID,
                          (UA_UInt32)notifications);
-    UA_SecureChannel_sendSymmetricMessage(sub->session->channel, pre->requestId,
+    UA_SecureChannel_sendSymmetricMessage(sub->session->header.channel, pre->requestId,
                                           UA_MESSAGETYPE_MSG, response,
                                           &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
 
@@ -427,7 +427,7 @@ UA_Subscription_reachedPublishReqLimit(UA_Server *server,  UA_Session *session)
     /* Send the response */
     UA_LOG_DEBUG_SESSION(server->config.logger, session,
                          "Sending out a publish response triggered by too many publish requests");
-    UA_SecureChannel_sendSymmetricMessage(session->channel, pre->requestId,
+    UA_SecureChannel_sendSymmetricMessage(session->header.channel, pre->requestId,
                                           UA_MESSAGETYPE_MSG, response,
                                           &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
 
@@ -494,7 +494,7 @@ UA_Subscription_answerPublishRequestsNoSubscription(UA_Server *server,
         UA_PublishResponse *response = &pre->response;
         response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION;
         response->responseHeader.timestamp = UA_DateTime_now();
-        UA_SecureChannel_sendSymmetricMessage(session->channel, pre->requestId,
+        UA_SecureChannel_sendSymmetricMessage(session->header.channel, pre->requestId,
                                               UA_MESSAGETYPE_MSG, response,
                                               &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
         UA_PublishResponse_deleteMembers(response);

+ 45 - 102
src/ua_securechannel.c

@@ -4,7 +4,6 @@
 
 #include "ua_util.h"
 #include "ua_securechannel.h"
-#include "ua_session.h"
 #include "ua_types_encoding_binary.h"
 #include "ua_types_generated_encoding_binary.h"
 #include "ua_transport_generated_encoding_binary.h"
@@ -34,16 +33,16 @@ UA_StatusCode
 UA_SecureChannel_init(UA_SecureChannel *channel,
                       const UA_SecurityPolicy *securityPolicy,
                       const UA_ByteString *remoteCertificate) {
-
     if(channel == NULL || securityPolicy == NULL || remoteCertificate == NULL)
         return UA_STATUSCODE_BADINTERNALERROR;
 
+    /* Linked lists are also initialized by zeroing out */
     memset(channel, 0, sizeof(UA_SecureChannel));
     channel->state = UA_SECURECHANNELSTATE_FRESH;
     channel->securityPolicy = securityPolicy;
 
-    UA_StatusCode retval = securityPolicy->channelModule.newContext(securityPolicy, remoteCertificate,
-                                                                    &channel->channelContext);
+    UA_StatusCode retval = securityPolicy->channelModule.
+        newContext(securityPolicy, remoteCertificate, &channel->channelContext);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
 
@@ -57,17 +56,10 @@ UA_SecureChannel_init(UA_SecureChannel *channel,
                                   &remoteCertificateThumbprint);
 
     return retval;
-    /* Linked lists are also initialized by zeroing out */
-    /* LIST_INIT(&channel->sessions); */
-    /* LIST_INIT(&channel->chunks); */
 }
 
 void
 UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel) {
-
-    if(channel == NULL)
-        return;
-
     /* Delete members */
     UA_ByteString_deleteMembers(&channel->remoteCertificate);
     UA_ByteString_deleteMembers(&channel->localNonce);
@@ -80,20 +72,18 @@ UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel) {
         channel->securityPolicy->channelModule.deleteContext(channel->channelContext);
 
     /* Detach from the connection and close the connection */
-    if(channel->connection){
-        if(channel->connection->state != UA_CONNECTION_CLOSED){
+    if(channel->connection) {
+        if(channel->connection->state != UA_CONNECTION_CLOSED)
             channel->connection->close(channel->connection);
-        }
         UA_Connection_detachSecureChannel(channel->connection);
     }
 
-    /* Remove session pointers (not the sessions) */
-    struct SessionEntry *se, *temp;
-    LIST_FOREACH_SAFE(se, &channel->sessions, pointers, temp) {
-        if(se->session)
-            se->session->channel = NULL;
-        LIST_REMOVE(se, pointers);
-        UA_free(se);
+    /* Remove session pointers (not the sessions) and NULL the pointers back to
+     * the SecureChannel in the Session */
+    UA_SessionHeader *sh, *temp;
+    LIST_FOREACH_SAFE(sh, &channel->sessions, pointers, temp) {
+        sh->channel = NULL;
+        LIST_REMOVE(sh, pointers);
     }
 
     /* Remove the buffered chunks */
@@ -106,28 +96,21 @@ UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel) {
 }
 
 UA_StatusCode
-UA_SecureChannel_generateNonce(const UA_SecureChannel *const channel,
-                               const size_t nonceLength,
-                               UA_ByteString *const nonce) {
-    if(channel == NULL || nonce == NULL)
-        return UA_STATUSCODE_BADINTERNALERROR;
-
+UA_SecureChannel_generateNonce(const UA_SecureChannel *channel,
+                               size_t nonceLength,
+                               UA_ByteString *nonce) {
     UA_ByteString_deleteMembers(nonce);
     UA_StatusCode retval = UA_ByteString_allocBuffer(nonce, nonceLength);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
 
-    return channel->securityPolicy->symmetricModule.generateNonce(channel->securityPolicy,
-                                                                  nonce);
+    return channel->securityPolicy->symmetricModule.
+        generateNonce(channel->securityPolicy, nonce);
 }
 
 UA_StatusCode
-UA_SecureChannel_generateNewKeys(UA_SecureChannel *const channel) {
-
-    if(channel == NULL)
-        return UA_STATUSCODE_BADINTERNALERROR;
-
-    const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
+UA_SecureChannel_generateNewKeys(UA_SecureChannel *channel) {
+    const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
     const UA_SecurityPolicyChannelModule *channelModule =
         &securityPolicy->channelModule;
     const UA_SecurityPolicySymmetricModule *symmetricModule =
@@ -174,44 +157,15 @@ UA_SecureChannel_generateNewKeys(UA_SecureChannel *const channel) {
     return retval;
 }
 
-void
-UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session) {
-    struct SessionEntry *se = (struct SessionEntry *) UA_malloc(sizeof(struct SessionEntry));
-    if(!se)
-        return;
-    se->session = session;
-    if(UA_atomic_cmpxchg((void **) &session->channel, NULL, channel) != NULL) {
-        UA_free(se);
-        return;
-    }
-    LIST_INSERT_HEAD(&channel->sessions, se, pointers);
-}
-
-void
-UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session) {
-    if(session)
-        session->channel = NULL;
-    struct SessionEntry *se;
-    LIST_FOREACH(se, &channel->sessions, pointers) {
-        if(se->session == session)
-            break;
-    }
-    if(!se)
-        return;
-    LIST_REMOVE(se, pointers);
-    UA_free(se);
-}
-
-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))
+UA_SessionHeader *
+UA_SecureChannel_getSession(UA_SecureChannel *channel,
+                            const UA_NodeId *authenticationToken) {
+    struct UA_SessionHeader *sh;
+    LIST_FOREACH(sh, &channel->sessions, pointers) {
+        if(UA_NodeId_equal(&sh->authenticationToken, authenticationToken))
             break;
     }
-    if(!se)
-        return NULL;
-    return se->session;
+    return sh;
 }
 
 UA_StatusCode
@@ -240,7 +194,8 @@ calculatePaddingAsym(const UA_SecurityPolicy *securityPolicy, const void *channe
     if(securityPolicy->asymmetricModule.cryptoModule.
        getRemoteEncryptionKeyLength(securityPolicy, channelContext) > 2048)
         ++paddingBytes;
-    size_t padding = (plainTextBlockSize - ((bytesToWrite + signatureSize + paddingBytes) % plainTextBlockSize));
+    size_t padding = (plainTextBlockSize - ((bytesToWrite + signatureSize + paddingBytes) %
+                                            plainTextBlockSize));
     *paddingSize = (UA_Byte) (padding & 0xff);
     *extraPaddingSize = (UA_Byte) (padding >> 8);
     return (UA_UInt16) padding;
@@ -252,7 +207,7 @@ calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
                               channel->securityPolicy->policyUri.length;
     if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
        channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
-        // OPN is always encrypted even if mode sign only
+        /* OPN is always encrypted even if mode sign only */
         asymHeaderLength += 20; /* Thumbprints are always 20 byte long */
         asymHeaderLength += channel->securityPolicy->localCertificate.length;
     }
@@ -260,9 +215,8 @@ calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
 }
 
 static void
-hideBytesAsym(UA_SecureChannel *const channel, UA_Byte **const buf_start,
-              const UA_Byte **const buf_end) {
-    const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
+hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start, const UA_Byte **buf_end) {
+    const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
     *buf_start += UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + UA_SEQUENCE_HEADER_LENGTH;
 
     /* Add the SecurityHeaderLength */
@@ -274,7 +228,7 @@ hideBytesAsym(UA_SecureChannel *const channel, UA_Byte **const buf_start,
        channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
         *buf_end -= securityPolicy->asymmetricModule.cryptoModule.
             getLocalSignatureSize(securityPolicy, channel->channelContext);
-        *buf_end -= 2; // padding byte and extraPadding byte
+        *buf_end -= 2; /* padding byte and extraPadding byte */
 
         /* Add some overhead length due to RSA implementations adding a signature themselves */
         *buf_end -= securityPolicy->channelModule.
@@ -287,9 +241,6 @@ hideBytesAsym(UA_SecureChannel *const channel, UA_Byte **const buf_start,
 UA_StatusCode
 UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
                                           const void *content, const UA_DataType *contentType) {
-    if(channel == NULL || content == NULL || contentType == NULL)
-        return UA_STATUSCODE_BADINTERNALERROR;
-
     if(channel->securityMode == UA_MESSAGESECURITYMODE_INVALID)
         return UA_STATUSCODE_BADSECURITYMODEREJECTED;
 
@@ -312,8 +263,7 @@ UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel, UA_UInt32 r
 
     /* Encode the message type and content */
     UA_NodeId typeId = UA_NODEID_NUMERIC(0, contentType->binaryEncodingId);
-    retval = UA_encodeBinary(&typeId, &UA_TYPES[UA_TYPES_NODEID],
-                             &buf_pos, &buf_end, NULL, NULL);
+    retval = UA_encodeBinary(&typeId, &UA_TYPES[UA_TYPES_NODEID], &buf_pos, &buf_end, NULL, NULL);
     retval |= UA_encodeBinary(content, contentType, &buf_pos, &buf_end, NULL, NULL);
     if(retval != UA_STATUSCODE_GOOD) {
         connection->releaseSendBuffer(connection, &buf);
@@ -712,7 +662,7 @@ UA_SecureChannel_removeChunks(UA_SecureChannel *channel, UA_UInt32 requestId) {
 }
 
 static UA_StatusCode
-appendChunk(struct ChunkEntry *const chunkEntry, const UA_ByteString *const chunkBody) {
+appendChunk(struct ChunkEntry *chunkEntry, const UA_ByteString *chunkBody) {
     UA_Byte *new_bytes = (UA_Byte *)
         UA_realloc(chunkEntry->bytes.data, chunkEntry->bytes.length + chunkBody->length);
     if(!new_bytes) {
@@ -749,7 +699,7 @@ UA_SecureChannel_appendChunk(UA_SecureChannel *channel, UA_UInt32 requestId,
 
 static UA_StatusCode
 UA_SecureChannel_finalizeChunk(UA_SecureChannel *channel, UA_UInt32 requestId,
-                               const UA_ByteString *const chunkBody, UA_MessageType messageType,
+                               const UA_ByteString *chunkBody, UA_MessageType messageType,
                                UA_ProcessMessageCallback callback, void *application) {
     struct ChunkEntry *chunkEntry;
     LIST_FOREACH(chunkEntry, &channel->chunks, pointers) {
@@ -781,16 +731,12 @@ UA_SecureChannel_finalizeChunk(UA_SecureChannel *channel, UA_UInt32 requestId,
 
 static UA_StatusCode
 decryptChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cryptoModule,
-             UA_ByteString *chunk, size_t offset, UA_UInt32 *requestId,
-             UA_UInt32 *sequenceNumber, UA_ByteString *payload,
-             UA_MessageType messageType) {
+             UA_ByteString *chunk, size_t offset, UA_UInt32 *requestId, UA_UInt32 *sequenceNumber,
+             UA_ByteString *payload, UA_MessageType messageType) {
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
     size_t chunkSizeAfterDecryption = chunk->length;
 
-    if(cryptoModule == NULL)
-        return UA_STATUSCODE_BADINTERNALERROR;
-
     /* Decrypt the chunk. Always decrypt opn messages if mode not none */
     if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
        messageType == UA_MESSAGETYPE_OPN) {
@@ -864,7 +810,6 @@ processSequenceNumberAsym(UA_SecureChannel *const channel, UA_UInt32 sequenceNum
     return UA_STATUSCODE_GOOD;
 }
 
-// TODO: We somehow need to make sure that a sequence number is never reused for the same tokenId
 static UA_StatusCode
 processSequenceNumberSym(UA_SecureChannel *const channel, UA_UInt32 sequenceNumber) {
     /* Failure mode hook for unit tests */
@@ -875,7 +820,8 @@ processSequenceNumberSym(UA_SecureChannel *const channel, UA_UInt32 sequenceNumb
 
     /* Does the sequence number match? */
     if(sequenceNumber != channel->receiveSequenceNumber + 1) {
-        if(channel->receiveSequenceNumber + 1 > 4294966271 && sequenceNumber < 1024) // FIXME: Remove magic numbers :(
+        /* FIXME: Remove magic numbers :( */
+        if(channel->receiveSequenceNumber + 1 > 4294966271 && sequenceNumber < 1024)
             channel->receiveSequenceNumber = sequenceNumber - 1; /* Roll over */
         else
             return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
@@ -972,7 +918,7 @@ UA_SecureChannel_processChunk(UA_SecureChannel *channel, UA_ByteString *chunk,
             return retval;
 
 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-        // let's help fuzzing by setting the correct tokenId
+        /* Help fuzzing by always setting the correct tokenId */
         symmetricSecurityHeader.tokenId = channel->securityToken.tokenId;
 #endif
 
@@ -982,7 +928,6 @@ UA_SecureChannel_processChunk(UA_SecureChannel *channel, UA_ByteString *chunk,
 
         cryptoModule = &channel->securityPolicy->symmetricModule.cryptoModule;
         sequenceNumberCallback = processSequenceNumberSym;
-
         break;
     }
     case UA_MESSAGETYPE_OPN: {
@@ -990,25 +935,22 @@ UA_SecureChannel_processChunk(UA_SecureChannel *channel, UA_ByteString *chunk,
         if(chunkType != UA_CHUNKTYPE_FINAL)
             return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
 
-        // Decode the asymmetric algorithm security header and
-        // call the callback to perform checks.
+        /* Decode the asymmetric algorithm security header and call the callback
+         * to perform checks. */
         UA_AsymmetricAlgorithmSecurityHeader asymHeader;
         UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
         offset = UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH;
-        retval = UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(chunk,
-                                                                   &offset,
-                                                                   &asymHeader);
+        retval = UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(chunk, &offset, &asymHeader);
         if(retval != UA_STATUSCODE_GOOD)
-            break;
+            return retval;
 
         retval = checkAsymHeader(channel, &asymHeader);
         UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
         if(retval != UA_STATUSCODE_GOOD)
-            break;
+            return retval;
 
         cryptoModule = &channel->securityPolicy->asymmetricModule.cryptoModule;
         sequenceNumberCallback = processSequenceNumberAsym;
-
         break;
     }
     default:
@@ -1016,6 +958,7 @@ UA_SecureChannel_processChunk(UA_SecureChannel *channel, UA_ByteString *chunk,
     }
 
     /* Decrypt message */
+    UA_assert(cryptoModule != NULL);
     retval = decryptChunk(channel, cryptoModule, chunk, offset, &requestId,
                           &sequenceNumber, &chunkPayload, messageType);
     if(retval != UA_STATUSCODE_GOOD)

+ 38 - 29
src/ua_securechannel.h

@@ -15,7 +15,6 @@ extern "C" {
 #include "ua_connection_internal.h"
 #include "ua_plugin_securitypolicy.h"
 #include "ua_plugin_log.h"
-#include "ua_util.h"
 
 #define UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH 12
 #define UA_SECURE_MESSAGE_HEADER_LENGTH 24
@@ -26,12 +25,18 @@ extern UA_THREAD_LOCAL UA_StatusCode sendAsym_sendFailure;
 extern UA_THREAD_LOCAL UA_StatusCode processSym_seqNumberFailure;
 #endif
 
-struct UA_Session;
-typedef struct UA_Session UA_Session;
-
-struct SessionEntry {
-    LIST_ENTRY(SessionEntry) pointers;
-    UA_Session *session; // Just a pointer. The session is held in the session manager or the client
+/* The Session implementation differs between client and server. Still, it is
+ * expected that the Session structure begins with the SessionHeader. This is
+ * the interface that will be used by the SecureChannel. The lifecycle of
+ * Sessions is independent of the underlying SecureChannel. But every Session
+ * can be attached to only one SecureChannel. */
+struct UA_SessionHeader;
+typedef struct UA_SessionHeader UA_SessionHeader;
+
+struct UA_SessionHeader {
+    LIST_ENTRY(UA_SessionHeader) pointers;
+    UA_NodeId authenticationToken;
+    UA_SecureChannel *channel; /* The pointer back to the SecureChannel in the session. */
 };
 
 /* For chunked requests */
@@ -69,7 +74,7 @@ struct UA_SecureChannel {
     UA_UInt32 receiveSequenceNumber;
     UA_UInt32 sendSequenceNumber;
 
-    LIST_HEAD(session_pointerlist, SessionEntry) sessions;
+    LIST_HEAD(session_pointerlist, UA_SessionHeader) sessions;
     LIST_HEAD(chunk_pointerlist, ChunkEntry) chunks;
 };
 
@@ -80,35 +85,43 @@ UA_SecureChannel_init(UA_SecureChannel *channel,
 void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel);
 
 /* Generates new keys and sets them in the channel context */
-UA_StatusCode UA_SecureChannel_generateNewKeys(UA_SecureChannel* const channel);
+UA_StatusCode
+UA_SecureChannel_generateNewKeys(UA_SecureChannel* channel);
 
-/* Wrapper function for generating nonces for the supplied channel.
+/* Wrapper function for generating nonces for the supplied channel. Uses the
+ * random generator of the channels security policy to allocate and generate a
+ * nonce with the specified length.
  *
- * Uses the random generator of the channels security policy to allocate
- * and generate a nonce with the specified length.
- *
- * \param channel the channel to use.
- * \param nonceLength the length of the nonce to be generated.
- * \param nonce will contain the nonce after being successfully called.
- */
-UA_StatusCode UA_SecureChannel_generateNonce(const UA_SecureChannel *const channel,
-                                             const size_t nonceLength,
-                                             UA_ByteString *const nonce);
-
-void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session);
-void UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session);
-UA_Session * UA_SecureChannel_getSession(UA_SecureChannel *channel, UA_NodeId *token);
-UA_StatusCode UA_SecureChannel_revolveTokens(UA_SecureChannel *channel);
+ * @param channel the channel to use.
+ * @param nonceLength the length of the nonce to be generated.
+ * @param nonce will contain the nonce after being successfully called. */
+UA_StatusCode
+UA_SecureChannel_generateNonce(const UA_SecureChannel *channel,
+                               size_t nonceLength, UA_ByteString *nonce);
+
+UA_SessionHeader *
+UA_SecureChannel_getSession(UA_SecureChannel *channel,
+                            const UA_NodeId *authenticationToken);
+
+UA_StatusCode
+UA_SecureChannel_revolveTokens(UA_SecureChannel *channel);
 
 /**
  * Sending Messages
  * ---------------- */
 
+UA_StatusCode
+UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
+                                          const void *content, const UA_DataType *contentType);
+
 UA_StatusCode
 UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
                                       UA_MessageType messageType, void *payload,
                                       const UA_DataType *payloadType);
 
+/* The MessageContext is forwarded into the encoding layer so that we can send
+ * chunks before continuing to encode. This lets us reuse a fixed chunk-sized
+ * messages buffer. */
 typedef struct {
     UA_SecureChannel *channel;
     UA_UInt32 requestId;
@@ -147,10 +160,6 @@ UA_MessageContext_finish(UA_MessageContext *mc);
 void
 UA_MessageContext_abort(UA_MessageContext *mc);
 
-UA_StatusCode
-UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
-                                          const void *content, const UA_DataType *contentType);
-
 /**
  * Process Received Chunks
  * ----------------------- */

+ 251 - 350
tests/check_securechannel.c

@@ -87,100 +87,60 @@ teardown_key_sizes(void) {
     memset(&keySizes, 0, sizeof(struct key_sizes));
 }
 
-/*
-static void
-setup_dummyPolicy(void) {
-    TestingPolicy(&dummyPolicy, dummyCertificate, &fCalled);
-}
-
-static void
-teardown_dummyPolicy(void) {
-    dummyPolicy.deleteMembers(&dummyPolicy);
-}*/
-
-START_TEST(SecureChannel_initAndDelete)
-    {
-        TestingPolicy(&dummyPolicy, dummyCertificate, &fCalled, &keySizes);
-        UA_StatusCode retval;
-
-        UA_SecureChannel channel;
-        retval = UA_SecureChannel_init(&channel, &dummyPolicy, &dummyCertificate);
-
-        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected StatusCode to be good");
-        ck_assert_msg(channel.state == UA_SECURECHANNELSTATE_FRESH, "Expected state to be fresh");
-        ck_assert_msg(fCalled.newContext, "Expected newContext to have been called");
-        ck_assert_msg(fCalled.makeCertificateThumbprint, "Expected makeCertificateThumbprint to have been called");
-        ck_assert_msg(channel.securityPolicy == &dummyPolicy, "SecurityPolicy not set correctly");
-
-        UA_SecureChannel_deleteMembersCleanup(&channel);
-        ck_assert_msg(fCalled.deleteContext, "Expected deleteContext to have been called");
-
-        dummyPolicy.deleteMembers(&dummyPolicy);
-    }
-END_TEST
-
-START_TEST(SecureChannel_initAndDelete_invalidParameters)
-    {
-        UA_StatusCode retval = UA_SecureChannel_init(NULL, NULL, NULL);
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected init to fail");
-
-        UA_SecureChannel channel;
-        retval = UA_SecureChannel_init(&channel, &dummyPolicy, NULL);
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected init to fail");
-
-        retval = UA_SecureChannel_init(&channel, NULL, &dummyCertificate);
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected init to fail");
-
-        retval = UA_SecureChannel_init(NULL, &dummyPolicy, &dummyCertificate);
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected init to fail");
-
-        UA_SecureChannel_deleteMembersCleanup(NULL);
-    }
-END_TEST
+START_TEST(SecureChannel_initAndDelete) {
+    TestingPolicy(&dummyPolicy, dummyCertificate, &fCalled, &keySizes);
+    UA_StatusCode retval;
 
+    UA_SecureChannel channel;
+    retval = UA_SecureChannel_init(&channel, &dummyPolicy, &dummyCertificate);
 
-START_TEST(SecureChannel_generateNewKeys)
-    {
-        UA_StatusCode retval = UA_SecureChannel_generateNewKeys(&testChannel);
+    ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected StatusCode to be good");
+    ck_assert_msg(channel.state == UA_SECURECHANNELSTATE_FRESH, "Expected state to be fresh");
+    ck_assert_msg(fCalled.newContext, "Expected newContext to have been called");
+    ck_assert_msg(fCalled.makeCertificateThumbprint, "Expected makeCertificateThumbprint to have been called");
+    ck_assert_msg(channel.securityPolicy == &dummyPolicy, "SecurityPolicy not set correctly");
 
-        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected Statuscode to be good");
-        ck_assert_msg(fCalled.generateKey, "Expected generateKey to have been called");
-        ck_assert_msg(fCalled.setLocalSymEncryptingKey, "Expected setLocalSymEncryptingKey to have been called");
-        ck_assert_msg(fCalled.setLocalSymSigningKey, "Expected setLocalSymSigningKey to have been called");
-        ck_assert_msg(fCalled.setLocalSymIv, "Expected setLocalSymIv to have been called");
-        ck_assert_msg(fCalled.setRemoteSymEncryptingKey, "Expected setRemoteSymEncryptingKey to have been called");
-        ck_assert_msg(fCalled.setRemoteSymSigningKey, "Expected setRemoteSymSigningKey to have been called");
-        ck_assert_msg(fCalled.setRemoteSymIv, "Expected setRemoteSymIv to have been called");
+    UA_SecureChannel_deleteMembersCleanup(&channel);
+    ck_assert_msg(fCalled.deleteContext, "Expected deleteContext to have been called");
 
-        retval = UA_SecureChannel_generateNewKeys(NULL);
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected failure on NULL pointer");
-    }
-END_TEST
-
-START_TEST(SecureChannel_revolveTokens)
-    {
-        // Fake that no token was issued by setting 0
-        testChannel.nextSecurityToken.tokenId = 0;
-        UA_StatusCode retval = UA_SecureChannel_revolveTokens(&testChannel);
-        ck_assert_msg(retval == UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN,
-                      "Expected failure because tokenId 0 signifies that no token was issued");
-
-        // Fake an issued token by setting an id
-        testChannel.nextSecurityToken.tokenId = 10;
-        retval = UA_SecureChannel_revolveTokens(&testChannel);
-        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to return GOOD");
-        ck_assert_msg(fCalled.generateKey,
-                      "Expected generateKey to be called because new keys need to be generated,"
-                          "when switching to the next token.");
-
-        UA_ChannelSecurityToken testToken;
-        UA_ChannelSecurityToken_init(&testToken);
-
-        ck_assert_msg(memcmp(&testChannel.nextSecurityToken, &testToken, sizeof(UA_ChannelSecurityToken)) == 0,
-                      "Expected the next securityToken to be freshly initialized");
-        ck_assert_msg(testChannel.securityToken.tokenId == 10, "Expected token to have been copied");
-    }
-END_TEST
+    dummyPolicy.deleteMembers(&dummyPolicy);
+} END_TEST
+
+START_TEST(SecureChannel_generateNewKeys) {
+    UA_StatusCode retval = UA_SecureChannel_generateNewKeys(&testChannel);
+
+    ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected Statuscode to be good");
+    ck_assert_msg(fCalled.generateKey, "Expected generateKey to have been called");
+    ck_assert_msg(fCalled.setLocalSymEncryptingKey, "Expected setLocalSymEncryptingKey to have been called");
+    ck_assert_msg(fCalled.setLocalSymSigningKey, "Expected setLocalSymSigningKey to have been called");
+    ck_assert_msg(fCalled.setLocalSymIv, "Expected setLocalSymIv to have been called");
+    ck_assert_msg(fCalled.setRemoteSymEncryptingKey, "Expected setRemoteSymEncryptingKey to have been called");
+    ck_assert_msg(fCalled.setRemoteSymSigningKey, "Expected setRemoteSymSigningKey to have been called");
+    ck_assert_msg(fCalled.setRemoteSymIv, "Expected setRemoteSymIv to have been called");
+} END_TEST
+
+START_TEST(SecureChannel_revolveTokens) {
+    // Fake that no token was issued by setting 0
+    testChannel.nextSecurityToken.tokenId = 0;
+    UA_StatusCode retval = UA_SecureChannel_revolveTokens(&testChannel);
+    ck_assert_msg(retval == UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN,
+                  "Expected failure because tokenId 0 signifies that no token was issued");
+
+    // Fake an issued token by setting an id
+    testChannel.nextSecurityToken.tokenId = 10;
+    retval = UA_SecureChannel_revolveTokens(&testChannel);
+    ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to return GOOD");
+    ck_assert_msg(fCalled.generateKey,
+                  "Expected generateKey to be called because new keys need to be generated,"
+                  "when switching to the next token.");
+
+    UA_ChannelSecurityToken testToken;
+    UA_ChannelSecurityToken_init(&testToken);
+
+    ck_assert_msg(memcmp(&testChannel.nextSecurityToken, &testToken, sizeof(UA_ChannelSecurityToken)) == 0,
+                  "Expected the next securityToken to be freshly initialized");
+    ck_assert_msg(testChannel.securityToken.tokenId == 10, "Expected token to have been copied");
+} END_TEST
 
 static void
 createDummyResponse(UA_OpenSecureChannelResponse *response) {
@@ -188,303 +148,246 @@ createDummyResponse(UA_OpenSecureChannelResponse *response) {
     memset(response, 0, sizeof(UA_OpenSecureChannelResponse));
 }
 
-START_TEST(SecureChannel_sendAsymmetricOPNMessage_withoutConnection)
-    {
-        UA_OpenSecureChannelResponse dummyResponse;
-        createDummyResponse(&dummyResponse);
-        testChannel.securityMode = UA_MESSAGESECURITYMODE_NONE;
+START_TEST(SecureChannel_sendAsymmetricOPNMessage_withoutConnection) {
+    UA_OpenSecureChannelResponse dummyResponse;
+    createDummyResponse(&dummyResponse);
+    testChannel.securityMode = UA_MESSAGESECURITYMODE_NONE;
 
-        // Remove connection to provoke error
-        UA_Connection_detachSecureChannel(testChannel.connection);
-        testChannel.connection = NULL;
+    // Remove connection to provoke error
+    UA_Connection_detachSecureChannel(testChannel.connection);
+    testChannel.connection = NULL;
 
-        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
-                                                                         42,
-                                                                         &dummyResponse,
-                                                                         &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
+    UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel, 42, &dummyResponse,
+                                                                     &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
 
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected failure without a connection");
-    }
-END_TEST
+    ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected failure without a connection");
+} END_TEST
 
-START_TEST(SecureChannel_sendAsymmetricOPNMessage_invalidParameters)
-    {
+START_TEST(SecureChannel_sendAsymmetricOPNMessage_invalidParameters) {
         UA_OpenSecureChannelResponse dummyResponse;
         createDummyResponse(&dummyResponse);
 
-        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
-                                                                         42,
-                                                                         NULL,
+        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel, 42, NULL,
                                                                          &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
         ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected failure");
 
-        retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
-                                                           42,
-                                                           &dummyResponse,
-                                                           NULL);
+        retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel, 42, &dummyResponse, NULL);
         ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected failure");
 
-        retval = UA_SecureChannel_sendAsymmetricOPNMessage(NULL,
-                                                           42,
-                                                           &dummyResponse,
-                                                           &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected failure");
-    }
-END_TEST
+} END_TEST
 
-START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeInvalid)
-    {
-        // Configure our channel correctly for OPN messages and setup dummy message
-        UA_OpenSecureChannelResponse dummyResponse;
-        createDummyResponse(&dummyResponse);
+START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeInvalid) {
+    // Configure our channel correctly for OPN messages and setup dummy message
+    UA_OpenSecureChannelResponse dummyResponse;
+    createDummyResponse(&dummyResponse);
 
-        testChannel.securityMode = UA_MESSAGESECURITYMODE_INVALID;
+    testChannel.securityMode = UA_MESSAGESECURITYMODE_INVALID;
 
-        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
-                                                                         42,
-                                                                         &dummyResponse,
-                                                                         &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
-        ck_assert_msg(retval == UA_STATUSCODE_BADSECURITYMODEREJECTED, "Expected SecurityMode rejected error");
-    }
+    UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel, 42, &dummyResponse,
+                                                                     &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
+    ck_assert_msg(retval == UA_STATUSCODE_BADSECURITYMODEREJECTED, "Expected SecurityMode rejected error");
+}
 END_TEST
 
-START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeNone)
-    {
-        // Configure our channel correctly for OPN messages and setup dummy message
-        UA_OpenSecureChannelResponse dummyResponse;
-        createDummyResponse(&dummyResponse);
-        testChannel.securityMode = UA_MESSAGESECURITYMODE_NONE;
-
-        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
-                                                                         42,
-                                                                         &dummyResponse,
-                                                                         &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
-        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
-        ck_assert_msg(!fCalled.asym_enc, "Message encryption was called but should not have been");
-        ck_assert_msg(!fCalled.asym_sign, "Message signing was called but should not have been");
-    }
+START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeNone) {
+    // Configure our channel correctly for OPN messages and setup dummy message
+    UA_OpenSecureChannelResponse dummyResponse;
+    createDummyResponse(&dummyResponse);
+    testChannel.securityMode = UA_MESSAGESECURITYMODE_NONE;
+
+    UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel, 42, &dummyResponse,
+                                                                     &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
+    ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
+    ck_assert_msg(!fCalled.asym_enc, "Message encryption was called but should not have been");
+    ck_assert_msg(!fCalled.asym_sign, "Message signing was called but should not have been");
+}
 END_TEST
 
-START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeSign)
-    {
-        // Configure our channel correctly for OPN messages and setup dummy message
-        UA_OpenSecureChannelResponse dummyResponse;
-        createDummyResponse(&dummyResponse);
-        testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGN;
-
-        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
-                                                                         42,
-                                                                         &dummyResponse,
-                                                                         &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
-        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
-        ck_assert_msg(fCalled.asym_enc, "Expected message to have been encrypted but it was not");
-        ck_assert_msg(fCalled.asym_sign, "Expected message to have been signed but it was not");
+START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeSign) {
+    // Configure our channel correctly for OPN messages and setup dummy message
+    UA_OpenSecureChannelResponse dummyResponse;
+    createDummyResponse(&dummyResponse);
+    testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGN;
+
+    UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel, 42, &dummyResponse,
+                                                                     &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
+    ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
+    ck_assert_msg(fCalled.asym_enc, "Expected message to have been encrypted but it was not");
+    ck_assert_msg(fCalled.asym_sign, "Expected message to have been signed but it was not");
+} END_TEST
+
+START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeSignAndEncrypt) {
+    // Configure our channel correctly for OPN messages and setup dummy message
+    UA_OpenSecureChannelResponse dummyResponse;
+    createDummyResponse(&dummyResponse);
+
+    testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT;
+    UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel, 42, &dummyResponse,
+                                                                     &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
+    ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
+    ck_assert_msg(fCalled.asym_enc, "Expected message to have been encrypted but it was not");
+    ck_assert_msg(fCalled.asym_sign, "Expected message to have been signed but it was not");
+} END_TEST
+
+START_TEST(SecureChannel_sendAsymmetricOPNMessage_sentDataIsValid) {
+    UA_OpenSecureChannelResponse dummyResponse;
+    createDummyResponse(&dummyResponse);
+
+    testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT;
+    UA_UInt32 requestId = UA_UInt32_random();
+
+    UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel, requestId, &dummyResponse,
+                                                                     &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
+    ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
+
+    size_t offset = 0;
+    UA_SecureConversationMessageHeader header;
+    UA_SecureConversationMessageHeader_decodeBinary(&sentData, &offset, &header);
+
+    UA_AsymmetricAlgorithmSecurityHeader asymSecurityHeader;
+    UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&sentData, &offset, &asymSecurityHeader);
+    ck_assert_msg(UA_ByteString_equal(&dummyCertificate, &asymSecurityHeader.senderCertificate),
+                  "Expected the certificate to be equal to the one used  by the secureChannel");
+    ck_assert_msg(UA_ByteString_equal(&testChannel.securityPolicy->policyUri,
+                                      &asymSecurityHeader.securityPolicyUri),
+                  "Expected securityPolicyUri to be equal to the one used by the secureChannel");
+    UA_ByteString thumbPrint = {20, testChannel.remoteCertificateThumbprint};
+    ck_assert_msg(UA_ByteString_equal(&thumbPrint,
+                                      &asymSecurityHeader.receiverCertificateThumbprint),
+                  "Expected receiverCertificateThumbprint to be equal to the one set in the secureChannel");
+
+    for(size_t i = offset; i < header.messageHeader.messageSize; ++i) {
+        sentData.data[i] = (UA_Byte) ((sentData.data[i] - 1) % (UA_BYTE_MAX + 1));
     }
-END_TEST
 
-START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeSignAndEncrypt)
-    {
-        // Configure our channel correctly for OPN messages and setup dummy message
-        UA_OpenSecureChannelResponse dummyResponse;
-        createDummyResponse(&dummyResponse);
+    UA_SequenceHeader sequenceHeader;
+    UA_SequenceHeader_decodeBinary(&sentData, &offset, &sequenceHeader);
+    ck_assert_msg(sequenceHeader.requestId == requestId, "Expected requestId to be %i but was %i",
+                  requestId,
+                  sequenceHeader.requestId);
 
-        testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT;
+    UA_NodeId original = UA_NODEID_NUMERIC(0, UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE].binaryEncodingId);
+    UA_NodeId requestTypeId;
+    UA_NodeId_decodeBinary(&sentData, &offset, &requestTypeId);
+    ck_assert_msg(UA_NodeId_equal(&original, &requestTypeId), "Expected nodeIds to be equal");
 
-        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
-                                                                         42,
-                                                                         &dummyResponse,
-                                                                         &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
-        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
-        ck_assert_msg(fCalled.asym_enc, "Expected message to have been encrypted but it was not");
-        ck_assert_msg(fCalled.asym_sign, "Expected message to have been signed but it was not");
-    }
-END_TEST
+    UA_OpenSecureChannelResponse sentResponse;
+    UA_OpenSecureChannelResponse_decodeBinary(&sentData, &offset, &sentResponse);
 
-START_TEST(SecureChannel_sendAsymmetricOPNMessage_sentDataIsValid)
-    {
-        UA_OpenSecureChannelResponse dummyResponse;
-        createDummyResponse(&dummyResponse);
+    ck_assert_msg(memcmp(&sentResponse, &dummyResponse, sizeof(UA_OpenSecureChannelResponse)) == 0,
+                  "Expected the sent response to be equal to the one supplied to the send function");
 
-        testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT;
-        UA_UInt32 requestId = UA_UInt32_random();
+    UA_Byte paddingByte = sentData.data[offset];
+    size_t paddingSize = (size_t) paddingByte;
 
-        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
-                                                                         requestId,
-                                                                         &dummyResponse,
-                                                                         &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
-        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
-
-        size_t offset = 0;
-        UA_SecureConversationMessageHeader header;
-        UA_SecureConversationMessageHeader_decodeBinary(&sentData, &offset, &header);
-
-        UA_AsymmetricAlgorithmSecurityHeader asymSecurityHeader;
-        UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&sentData, &offset, &asymSecurityHeader);
-        ck_assert_msg(UA_ByteString_equal(&dummyCertificate, &asymSecurityHeader.senderCertificate),
-                      "Expected the certificate to be equal to the one used  by the secureChannel");
-        ck_assert_msg(UA_ByteString_equal(&testChannel.securityPolicy->policyUri,
-                                          &asymSecurityHeader.securityPolicyUri),
-                      "Expected securityPolicyUri to be equal to the one used by the secureChannel");
-        UA_ByteString thumbPrint = {20, testChannel.remoteCertificateThumbprint};
-        ck_assert_msg(UA_ByteString_equal(&thumbPrint,
-                                          &asymSecurityHeader.receiverCertificateThumbprint),
-                      "Expected receiverCertificateThumbprint to be equal to the one set in the secureChannel");
-
-        for(size_t i = offset; i < header.messageHeader.messageSize; ++i) {
-            sentData.data[i] = (UA_Byte) ((sentData.data[i] - 1) % (UA_BYTE_MAX + 1));
-        }
-
-        UA_SequenceHeader sequenceHeader;
-        UA_SequenceHeader_decodeBinary(&sentData, &offset, &sequenceHeader);
-        ck_assert_msg(sequenceHeader.requestId == requestId, "Expected requestId to be %i but was %i",
-                      requestId,
-                      sequenceHeader.requestId);
-
-        UA_NodeId original = UA_NODEID_NUMERIC(0, UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE].binaryEncodingId);
-        UA_NodeId requestTypeId;
-        UA_NodeId_decodeBinary(&sentData, &offset, &requestTypeId);
-        ck_assert_msg(UA_NodeId_equal(&original, &requestTypeId), "Expected nodeIds to be equal");
-
-        UA_OpenSecureChannelResponse sentResponse;
-        UA_OpenSecureChannelResponse_decodeBinary(&sentData, &offset, &sentResponse);
-
-        ck_assert_msg(memcmp(&sentResponse, &dummyResponse, sizeof(UA_OpenSecureChannelResponse)) == 0,
-                      "Expected the sent response to be equal to the one supplied to the send function");
-
-        UA_Byte paddingByte = sentData.data[offset];
-        size_t paddingSize = (size_t) paddingByte;
-
-        for(size_t i = 0; i <= paddingSize; ++i) {
-            ck_assert_msg(sentData.data[offset + i] == paddingByte,
-                          "Expected padding byte %i to be %i but got value %i",
-                          i,
-                          paddingByte,
-                          sentData.data[offset + i]);
-        }
-
-        ck_assert_msg(sentData.data[offset + paddingSize + 1] == '*', "Expected first byte of signature");
-
-        UA_SecureConversationMessageHeader_deleteMembers(&header);
-        UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymSecurityHeader);
-        UA_SequenceHeader_deleteMembers(&sequenceHeader);
-        UA_OpenSecureChannelResponse_deleteMembers(&sentResponse);
+    for(size_t i = 0; i <= paddingSize; ++i) {
+        ck_assert_msg(sentData.data[offset + i] == paddingByte,
+                      "Expected padding byte %i to be %i but got value %i",
+                      i, paddingByte, sentData.data[offset + i]);
     }
-END_TEST
-
-START_TEST(Securechannel_sendAsymmetricOPNMessage_extraPaddingPresentWhenKeyLargerThan2048Bits)
-    {
-        keySizes.asym_rmt_enc_key_size = 4096;
-        keySizes.asym_rmt_ptext_blocksize = 4096;
-
-        UA_OpenSecureChannelResponse dummyResponse;
-        createDummyResponse(&dummyResponse);
 
-        testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT;
-        UA_UInt32 requestId = UA_UInt32_random();
+    ck_assert_msg(sentData.data[offset + paddingSize + 1] == '*', "Expected first byte of signature");
 
-        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
-                                                                         requestId,
-                                                                         &dummyResponse,
-                                                                         &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
-        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
-
-        size_t offset = 0;
-        UA_SecureConversationMessageHeader header;
-        UA_SecureConversationMessageHeader_decodeBinary(&sentData, &offset, &header);
-
-        UA_AsymmetricAlgorithmSecurityHeader asymSecurityHeader;
-        UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&sentData, &offset, &asymSecurityHeader);
-        ck_assert_msg(UA_ByteString_equal(&dummyCertificate, &asymSecurityHeader.senderCertificate),
-                      "Expected the certificate to be equal to the one used  by the secureChannel");
-        ck_assert_msg(UA_ByteString_equal(&testChannel.securityPolicy->policyUri,
-                                          &asymSecurityHeader.securityPolicyUri),
-                      "Expected securityPolicyUri to be equal to the one used by the secureChannel");
-        UA_ByteString thumbPrint = {20, testChannel.remoteCertificateThumbprint};
-        ck_assert_msg(UA_ByteString_equal(&thumbPrint,
-                                          &asymSecurityHeader.receiverCertificateThumbprint),
-                      "Expected receiverCertificateThumbprint to be equal to the one set in the secureChannel");
-
-        for(size_t i = offset; i < header.messageHeader.messageSize; ++i) {
-            sentData.data[i] = (UA_Byte) ((sentData.data[i] - 1) % (UA_BYTE_MAX + 1));
-        }
-
-        UA_SequenceHeader sequenceHeader;
-        UA_SequenceHeader_decodeBinary(&sentData, &offset, &sequenceHeader);
-        ck_assert_msg(sequenceHeader.requestId == requestId, "Expected requestId to be %i but was %i",
-                      requestId,
-                      sequenceHeader.requestId);
-
-        UA_NodeId original = UA_NODEID_NUMERIC(0, UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE].binaryEncodingId);
-        UA_NodeId requestTypeId;
-        UA_NodeId_decodeBinary(&sentData, &offset, &requestTypeId);
-        ck_assert_msg(UA_NodeId_equal(&original, &requestTypeId), "Expected nodeIds to be equal");
-
-        UA_OpenSecureChannelResponse sentResponse;
-        UA_OpenSecureChannelResponse_decodeBinary(&sentData, &offset, &sentResponse);
-
-        ck_assert_msg(memcmp(&sentResponse, &dummyResponse, sizeof(UA_OpenSecureChannelResponse)) == 0,
-                      "Expected the sent response to be equal to the one supplied to the send function");
-
-        UA_Byte paddingByte = sentData.data[offset];
-        UA_Byte extraPaddingByte = sentData.data[sentData.length - keySizes.asym_lcl_sig_size - 1];
-        size_t paddingSize = (size_t) paddingByte;
-        paddingSize |= extraPaddingByte << 8;
-
-        for(size_t i = 0; i <= paddingSize; ++i) {
-            ck_assert_msg(sentData.data[offset + i] == paddingByte,
-                          "Expected padding byte %i to be %i but got value %i",
-                          i,
-                          paddingByte,
-                          sentData.data[offset + i]);
-        }
-
-        ck_assert_msg(sentData.data[offset + paddingSize + 1] == extraPaddingByte, "Expected extra padding byte to be "
-            "%i but got %i",
-                      extraPaddingByte, sentData.data[offset + paddingSize + 1]);
-        ck_assert_msg(sentData.data[offset + paddingSize + 2] == '*', "Expected first byte 42 of signature but got %i",
-                      sentData.data[offset + paddingSize + 2]);
-
-        UA_SecureConversationMessageHeader_deleteMembers(&header);
-        UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymSecurityHeader);
-        UA_SequenceHeader_deleteMembers(&sequenceHeader);
-        UA_OpenSecureChannelResponse_deleteMembers(&sentResponse);
-    }
+    UA_SecureConversationMessageHeader_deleteMembers(&header);
+    UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymSecurityHeader);
+    UA_SequenceHeader_deleteMembers(&sequenceHeader);
+    UA_OpenSecureChannelResponse_deleteMembers(&sentResponse);
+}
 END_TEST
 
-START_TEST(SecureChannel_generateNonce)
-    {
-        UA_ByteString myNonce;
-        UA_ByteString_init(&myNonce);
-
-        for(size_t i = 0; i < 129; ++i) {
-            i = (i == 128) ? 65536 : i; // large edge case
+START_TEST(Securechannel_sendAsymmetricOPNMessage_extraPaddingPresentWhenKeyLargerThan2048Bits) {
+    keySizes.asym_rmt_enc_key_size = 4096;
+    keySizes.asym_rmt_ptext_blocksize = 4096;
+
+    UA_OpenSecureChannelResponse dummyResponse;
+    createDummyResponse(&dummyResponse);
+
+    testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT;
+    UA_UInt32 requestId = UA_UInt32_random();
+
+    UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel, requestId, &dummyResponse,
+                                                                     &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
+    ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
+
+    size_t offset = 0;
+    UA_SecureConversationMessageHeader header;
+    UA_SecureConversationMessageHeader_decodeBinary(&sentData, &offset, &header);
+
+    UA_AsymmetricAlgorithmSecurityHeader asymSecurityHeader;
+    UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&sentData, &offset, &asymSecurityHeader);
+    ck_assert_msg(UA_ByteString_equal(&dummyCertificate, &asymSecurityHeader.senderCertificate),
+                  "Expected the certificate to be equal to the one used  by the secureChannel");
+    ck_assert_msg(UA_ByteString_equal(&testChannel.securityPolicy->policyUri,
+                                      &asymSecurityHeader.securityPolicyUri),
+                  "Expected securityPolicyUri to be equal to the one used by the secureChannel");
+    UA_ByteString thumbPrint = {20, testChannel.remoteCertificateThumbprint};
+    ck_assert_msg(UA_ByteString_equal(&thumbPrint,
+                                      &asymSecurityHeader.receiverCertificateThumbprint),
+                  "Expected receiverCertificateThumbprint to be equal to the one set in the secureChannel");
+
+    for(size_t i = offset; i < header.messageHeader.messageSize; ++i) {
+        sentData.data[i] = (UA_Byte) ((sentData.data[i] - 1) % (UA_BYTE_MAX + 1));
+    }
 
-            UA_StatusCode retval = UA_SecureChannel_generateNonce(&testChannel, i, &myNonce);
+    UA_SequenceHeader sequenceHeader;
+    UA_SequenceHeader_decodeBinary(&sentData, &offset, &sequenceHeader);
+    ck_assert_msg(sequenceHeader.requestId == requestId, "Expected requestId to be %i but was %i",
+                  requestId,
+                  sequenceHeader.requestId);
+
+    UA_NodeId original = UA_NODEID_NUMERIC(0, UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE].binaryEncodingId);
+    UA_NodeId requestTypeId;
+    UA_NodeId_decodeBinary(&sentData, &offset, &requestTypeId);
+    ck_assert_msg(UA_NodeId_equal(&original, &requestTypeId), "Expected nodeIds to be equal");
+
+    UA_OpenSecureChannelResponse sentResponse;
+    UA_OpenSecureChannelResponse_decodeBinary(&sentData, &offset, &sentResponse);
+
+    ck_assert_msg(memcmp(&sentResponse, &dummyResponse, sizeof(UA_OpenSecureChannelResponse)) == 0,
+                  "Expected the sent response to be equal to the one supplied to the send function");
+
+    UA_Byte paddingByte = sentData.data[offset];
+    UA_Byte extraPaddingByte = sentData.data[sentData.length - keySizes.asym_lcl_sig_size - 1];
+    size_t paddingSize = (size_t) paddingByte;
+    paddingSize |= extraPaddingByte << 8;
+
+    for(size_t i = 0; i <= paddingSize; ++i) {
+        ck_assert_msg(sentData.data[offset + i] == paddingByte,
+                      "Expected padding byte %i to be %i but got value %i",
+                      i,
+                      paddingByte,
+                      sentData.data[offset + i]);
+    }
 
-            ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected retval to be good");
-            ck_assert_msg(myNonce.length == i, "Expected nonce length to be %i but was %i", i, myNonce.length);
-            ck_assert_msg(fCalled.generateNonce, "Expected generateNonce to have been called");
-        }
+    ck_assert_msg(sentData.data[offset + paddingSize + 1] == extraPaddingByte,
+                  "Expected extra padding byte to be %i but got %i",
+                  extraPaddingByte, sentData.data[offset + paddingSize + 1]);
+    ck_assert_msg(sentData.data[offset + paddingSize + 2] == '*',
+                  "Expected first byte 42 of signature but got %i",
+                  sentData.data[offset + paddingSize + 2]);
 
-        UA_ByteString_deleteMembers(&myNonce);
-    }
-END_TEST
+    UA_SecureConversationMessageHeader_deleteMembers(&header);
+    UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymSecurityHeader);
+    UA_SequenceHeader_deleteMembers(&sequenceHeader);
+    UA_OpenSecureChannelResponse_deleteMembers(&sentResponse);
+} END_TEST
 
-START_TEST(SecureChannel_generateNonce_invalidParameters)
-    {
-        UA_ByteString myNonce;
-        UA_ByteString_init(&myNonce);
+START_TEST(SecureChannel_generateNonce) {
+    UA_ByteString myNonce;
+    UA_ByteString_init(&myNonce);
 
-        UA_StatusCode retval = UA_SecureChannel_generateNonce(NULL, 42, NULL);
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected failure");
+    for(size_t i = 0; i < 129; ++i) {
+        i = (i == 128) ? 65536 : i; // large edge case
 
-        retval = UA_SecureChannel_generateNonce(NULL, 42, &myNonce);
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected failure");
+        UA_StatusCode retval = UA_SecureChannel_generateNonce(&testChannel, i, &myNonce);
 
-        retval = UA_SecureChannel_generateNonce(&testChannel, 42, NULL);
-        ck_assert_msg(retval != UA_STATUSCODE_GOOD, "Expected failure");
+        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected retval to be good");
+        ck_assert_msg(myNonce.length == i, "Expected nonce length to be %i but was %i", i, myNonce.length);
+        ck_assert_msg(fCalled.generateNonce, "Expected generateNonce to have been called");
     }
-END_TEST
+
+    UA_ByteString_deleteMembers(&myNonce);
+} END_TEST
 
 static Suite *
 testSuite_SecureChannel(void) {
@@ -494,7 +397,6 @@ testSuite_SecureChannel(void) {
     tcase_add_checked_fixture(tc_initAndDelete, setup_funcs_called, teardown_funcs_called);
     tcase_add_checked_fixture(tc_initAndDelete, setup_key_sizes, teardown_key_sizes);
     tcase_add_test(tc_initAndDelete, SecureChannel_initAndDelete);
-    tcase_add_test(tc_initAndDelete, SecureChannel_initAndDelete_invalidParameters);
     suite_add_tcase(s, tc_initAndDelete);
 
     TCase *tc_generateNewKeys = tcase_create("Test generateNewKeys function");
@@ -531,7 +433,6 @@ testSuite_SecureChannel(void) {
     tcase_add_checked_fixture(tc_generateNonce, setup_key_sizes, teardown_key_sizes);
     tcase_add_checked_fixture(tc_generateNonce, setup_secureChannel, teardown_secureChannel);
     tcase_add_test(tc_generateNonce, SecureChannel_generateNonce);
-    tcase_add_test(tc_generateNonce, SecureChannel_generateNonce_invalidParameters);
     suite_add_tcase(s, tc_generateNonce);
 
     return s;

+ 2 - 2
tests/server/check_session.c

@@ -20,9 +20,9 @@ START_TEST(Session_init_ShallWork) {
     UA_DateTime tmpDateTime;
     UA_DateTime_init(&tmpDateTime);
     ck_assert_int_eq(session.activated, false);
-    ck_assert_int_eq(session.authenticationToken.identifier.numeric, tmpNodeId.identifier.numeric);
+    ck_assert_int_eq(session.header.authenticationToken.identifier.numeric, tmpNodeId.identifier.numeric);
     ck_assert_int_eq(session.availableContinuationPoints, UA_MAXCONTINUATIONPOINTS);
-    ck_assert_ptr_eq(session.channel, NULL);
+    ck_assert_ptr_eq(session.header.channel, NULL);
     ck_assert_ptr_eq(session.clientDescription.applicationName.locale.data, NULL);
     ck_assert_ptr_eq(session.continuationPoints.lh_first, NULL);
     ck_assert_int_eq(session.maxRequestMessageSize, 0);