Quellcode durchsuchen

fix CTT Session base 008

Julius Pfrommer vor 8 Jahren
Ursprung
Commit
062709bb21
4 geänderte Dateien mit 60 neuen und 57 gelöschten Zeilen
  1. 2 2
      include/ua_connection.h
  2. 19 10
      src/server/ua_server_binary.c
  3. 31 38
      src/server/ua_services_session.c
  4. 8 7
      src/ua_securechannel.c

+ 2 - 2
include/ua_connection.h

@@ -96,8 +96,8 @@ struct UA_Connection {
 
     /* Receive a message from the remote connection
      *
-	 * @param connection The connection
-	 * @param response The response string. It is allocated by the connection
+     * @param connection The connection
+     * @param response The response string. It is allocated by the connection
      *        and needs to be freed with connection->releaseBuffer
      * @param timeout Timeout of the recv operation in milliseconds
      * @return Returns UA_STATUSCODE_BADCOMMUNICATIONERROR if the recv operation

+ 19 - 10
src/server/ua_server_binary.c

@@ -402,7 +402,7 @@ processRequest(UA_SecureChannel *channel, UA_Server *server, UA_UInt32 requestId
     UA_RequestHeader *requestHeader = (UA_RequestHeader*)request;
     retval = UA_decodeBinary(msg, pos, request, requestType);
     if(retval != UA_STATUSCODE_GOOD) {
-        sendError(channel, msg, requestPos, &UA_TYPES[UA_TYPES_SERVICEFAULT], requestId, retval);
+        sendError(channel, msg, requestPos, responseType, requestId, retval);
         return;
     }
 
@@ -410,18 +410,18 @@ processRequest(UA_SecureChannel *channel, UA_Server *server, UA_UInt32 requestId
     void *response = UA_alloca(responseType->memSize);
     UA_init(response, responseType);
 
-    /* Find the matching session */
-    UA_Session *session = UA_SecureChannel_getSession(channel, &requestHeader->authenticationToken);
-
-    /* CreateSession and ActivateSession don't need a session */
+    /* CreateSession doesn't need a session */
     if(requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]) {
         Service_CreateSession(server, channel, request, response);
         goto send_response;
     }
+
+    /* Find the matching session */
+    UA_Session *session = UA_SecureChannel_getSession(channel, &requestHeader->authenticationToken);
+    if(!session)
+        session = UA_SessionManager_getSession(&server->sessionManager, &requestHeader->authenticationToken);
+
     if(requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST]) {
-        /* Search in all sessions, not only those of the channel */
-        if(!session)
-            session = UA_SessionManager_getSession(&server->sessionManager, &requestHeader->authenticationToken);
         if(!session) {
             sendError(channel, msg, requestPos, responseType, requestId, UA_STATUSCODE_BADSESSIONIDINVALID);
             UA_deleteMembers(request, requestType);
@@ -442,7 +442,7 @@ processRequest(UA_SecureChannel *channel, UA_Server *server, UA_UInt32 requestId
             return;
         }
 
-        /* Set an anonymous, inactive session */
+        /* Set an anonymous, inactive session for services that need no session */
         UA_Session_init(&anonymousSession);
         anonymousSession.sessionId = UA_NODEID_NUMERIC(0,0);
         anonymousSession.channel = channel;
@@ -459,6 +459,14 @@ processRequest(UA_SecureChannel *channel, UA_Server *server, UA_UInt32 requestId
         return;
     }
 
+    /* The session is bound to another channel */
+    if(session->channel != channel) {
+        UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Client tries to use an obsolete securechannel");
+        sendError(channel, msg, requestPos, responseType, requestId, UA_STATUSCODE_BADSECURECHANNELIDINVALID);
+        UA_deleteMembers(request, requestType);
+        return;
+    }
+
     /* Update the session lifetime */
     UA_Session_updateLifetime(session);
 
@@ -512,7 +520,8 @@ processMSG(UA_Connection *connection, UA_Server *server, const UA_TcpMessageHead
     /* Is the channel attached to connection? */
     if(channelId != channel->securityToken.channelId) {
         UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_NETWORK,
-                    "Connection %i | Received MSG with the channel id not bound to the connection", connection->sockfd);
+                    "Connection %i | Received MSG with the channel id %i not bound to the connection",
+                    connection->sockfd, channelId);
         Service_CloseSecureChannel(server, channel);
     }
 

+ 31 - 38
src/server/ua_services_session.c

@@ -24,8 +24,8 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
         return;
     }
 
-    //TODO get maxResponseMessageSize internally
     newSession->maxResponseMessageSize = request->maxResponseMessageSize;
+    newSession->maxRequestMessageSize = channel->connection->localConf.maxMessageSize;
     response->sessionId = newSession->sessionId;
     response->revisedSessionTimeout = (UA_Double)newSession->timeout;
     response->authenticationToken = newSession->authenticationToken;
@@ -67,37 +67,22 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel, UA_Session
     UA_String up = UA_STRING(USERNAME_POLICY);
 
     /* Compatibility notice: Siemens OPC Scout v10 provides an empty policyId,
-       this is not okay For compatibility we will assume that empty policyId ==
-       ANONYMOUS_POLICY
+       this is not okay For compatibility we will assume that empty policyId == ANONYMOUS_POLICY
        if(token.policyId->data == NULL)
            response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
     */
 
-    /* anonymous login */
     if(server->config.enableAnonymousLogin &&
        request->userIdentityToken.content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
+        /* anonymous login */
         const UA_AnonymousIdentityToken *token = request->userIdentityToken.content.decoded.data;
         if(token->policyId.data && !UA_String_equal(&token->policyId, &ap)) {
             response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
             return;
         }
-        if(session->channel && session->channel != channel) {
-            /* Close the old SecureChannel (this also detaches it) */
-            UA_LOG_INFO_SESSION(server->config.logger, session,
-                                "ActivateSession: Detach from old channel");
-            UA_SecureChannelManager_close(&server->secureChannelManager,
-                                          session->channel->securityToken.channelId);
-        }
-        UA_SecureChannel_attachSession(channel, session);
-        session->activated = true;
-        UA_Session_updateLifetime(session);
-        UA_LOG_INFO_SESSION(server->config.logger, session, "ActivateSession: Session activated");
-        return;
-    }
-
-    /* username login */
-    if(server->config.enableUsernamePasswordLogin &&
-       request->userIdentityToken.content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
+    } else if(server->config.enableUsernamePasswordLogin &&
+              request->userIdentityToken.content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
+        /* username login */
         const UA_UserNameIdentityToken *token = request->userIdentityToken.content.decoded.data;
         if(!UA_String_equal(&token->policyId, &up)) {
             response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
@@ -108,31 +93,39 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel, UA_Session
             response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
             return;
         }
-        /* ok, trying to match the username */
+
+        /* trying to match pw/username */
+        UA_Boolean match = false;
         for(size_t i = 0; i < server->config.usernamePasswordLoginsSize; i++) {
             UA_String *user = &server->config.usernamePasswordLogins[i].username;
             UA_String *pw = &server->config.usernamePasswordLogins[i].password;
-            if(!UA_String_equal(&token->userName, user) || !UA_String_equal(&token->password, pw))
-                continue;
-            /* success - activate */
-            if(session->channel && session->channel != channel) {
-                UA_LOG_INFO_SESSION(server->config.logger, session,
-                                    "ActivateSession: Detach from old channel");
-                UA_SecureChannel_detachSession(session->channel, session);
+            if(UA_String_equal(&token->userName, user) && UA_String_equal(&token->password, pw)) {
+                match = true;
+                break;
             }
-            UA_SecureChannel_attachSession(channel, session);
-            session->activated = true;
-            UA_Session_updateLifetime(session);
-            UA_LOG_INFO_SESSION(server->config.logger, session, "ActivateSession: Session activated");
+        }
+        if(!match) {
+            UA_LOG_INFO_SESSION(server->config.logger, session, "ActivateSession: Did not find matching username/password");
+            response->responseHeader.serviceResult = UA_STATUSCODE_BADUSERACCESSDENIED;
             return;
         }
-        /* no match */
-        UA_LOG_INFO_SESSION(server->config.logger, session,
-                            "ActivateSession: Did not find matching username/password");
-        response->responseHeader.serviceResult = UA_STATUSCODE_BADUSERACCESSDENIED;
+    } else {
+        /* Unsupported token type */
+        response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
         return;
     }
-    response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+
+    /* Detach the old SecureChannel */
+    if(session->channel && session->channel != channel) {
+        UA_LOG_INFO_SESSION(server->config.logger, session, "ActivateSession: Detach from old channel");
+        UA_SecureChannel_detachSession(session->channel, session);
+    }
+
+    /* Attach to the SecureChannel and activate */
+    UA_SecureChannel_attachSession(channel, session);
+    session->activated = true;
+    UA_Session_updateLifetime(session);
+    UA_LOG_INFO_SESSION(server->config.logger, session, "ActivateSession: Session activated");
 }
 
 void

+ 8 - 7
src/ua_securechannel.c

@@ -92,14 +92,15 @@ void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *sessi
 void UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session) {
     if(session)
         session->channel = NULL;
-    struct SessionEntry *se, *temp;
-    LIST_FOREACH_SAFE(se, &channel->sessions, pointers, temp) {
-        if(se->session != session)
-            continue;
-        LIST_REMOVE(se, pointers);
-        UA_free(se);
-        break;
+    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) {