コード例 #1
0
ファイル: ua_server_binary.c プロジェクト: Pro/open62541
/* Takes decoded messages starting at the nodeid of the content type. Only OPN
 * messages start at the asymmetricalgorithmsecurityheader and are not
 * decoded. */
static void
UA_Server_processSecureChannelMessage(UA_Server *server, UA_SecureChannel *channel,
                                      UA_MessageType messagetype, UA_UInt32 requestId,
                                      const UA_ByteString *message) {
    switch(messagetype) {
    case UA_MESSAGETYPE_HEL:
        UA_LOG_TRACE_CHANNEL(server->config.logger, channel,
                             "Cannot process a HEL on an open channel");
        break;
    case UA_MESSAGETYPE_OPN:
        UA_LOG_TRACE_CHANNEL(server->config.logger, channel,
                             "Process an OPN on an open channel");
        processOPN(server, channel->connection, channel->securityToken.channelId, message);
        break;
    case UA_MESSAGETYPE_MSG:
        UA_LOG_TRACE_CHANNEL(server->config.logger, channel,
                             "Process a MSG", channel->connection->sockfd);
        processMSG(server, channel, requestId, message);
        break;
    case UA_MESSAGETYPE_CLO:
        UA_LOG_TRACE_CHANNEL(server->config.logger, channel,
                             "Process a CLO", channel->connection->sockfd);
        Service_CloseSecureChannel(server, channel);
        break;
    default:
        UA_LOG_TRACE_CHANNEL(server->config.logger, channel,
                             "Unknown message type");
    }
}
コード例 #2
0
ファイル: ua_server_binary.c プロジェクト: hfaham/open62541
static void processCLO(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) {
    UA_UInt32 secureChannelId;
    UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
    if(retval != UA_STATUSCODE_GOOD || !connection->channel ||
       connection->channel->securityToken.channelId != secureChannelId)
        return;
    Service_CloseSecureChannel(server, secureChannelId);
}
コード例 #3
0
ファイル: ua_server_binary.c プロジェクト: joerg555/open62541
static void processMSG(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) {
    /* Read in the securechannel */
    UA_UInt32 secureChannelId;
    UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
    if(retval != UA_STATUSCODE_GOOD)
        return;

    /* the anonymous channel is used e.g. to allow getEndpoints without a channel */
    UA_SecureChannel *clientChannel = connection->channel;
    UA_SecureChannel anonymousChannel;
    if(!clientChannel) {
        UA_SecureChannel_init(&anonymousChannel);
        anonymousChannel.connection = connection;
        clientChannel = &anonymousChannel;
    }

    /* Read the security header */
    UA_UInt32 tokenId = 0;
    UA_SequenceHeader sequenceHeader;
    retval = UA_UInt32_decodeBinary(msg, pos, &tokenId);
    retval |= UA_SequenceHeader_decodeBinary(msg, pos, &sequenceHeader);
#ifndef EXTENSION_STATELESS
    if(retval != UA_STATUSCODE_GOOD || tokenId == 0) // 0 is invalid
        return;
#else
    if(retval != UA_STATUSCODE_GOOD)
        return;
#endif

    if(clientChannel != &anonymousChannel && tokenId != clientChannel->securityToken.tokenId) {
        if(tokenId != clientChannel->nextSecurityToken.tokenId) {
            /* close the securechannel but keep the connection open */
            UA_LOG_INFO(server->logger, UA_LOGCATEGORY_SECURECHANNEL,
                        "Request with a wrong security token. Closing the SecureChannel %i.",
                        clientChannel->securityToken.channelId);
            Service_CloseSecureChannel(server, clientChannel->securityToken.channelId);
            return;
        }
        UA_SecureChannel_revolveTokens(clientChannel);
    }

    /* Read the request type */
    UA_NodeId requestType;
    if(UA_NodeId_decodeBinary(msg, pos, &requestType) != UA_STATUSCODE_GOOD)
        return;
    if(requestType.identifierType != UA_NODEIDTYPE_NUMERIC) {
        UA_NodeId_deleteMembers(&requestType);
        return;
    }

    switch(requestType.identifier.numeric - UA_ENCODINGOFFSET_BINARY) {
    case UA_NS0ID_GETENDPOINTSREQUEST: {
        if(clientChannel == &anonymousChannel)
            UA_LOG_DEBUG(server->logger, UA_LOGCATEGORY_NETWORK, "Processing GetEndpointsRequest on Connection %i",
                         connection->sockfd);
        else
            UA_LOG_DEBUG(server->logger, UA_LOGCATEGORY_SECURECHANNEL, "Processing GetEndpointsRequest on SecureChannel %i",
                         clientChannel->securityToken.channelId);
        UA_GetEndpointsRequest p;
        UA_GetEndpointsResponse r;
        if(UA_GetEndpointsRequest_decodeBinary(msg, pos, &p))
            return;
        UA_GetEndpointsResponse_init(&r);
        init_response_header(&p.requestHeader, &r.responseHeader);
        Service_GetEndpoints(server, &p, &r);
        UA_GetEndpointsRequest_deleteMembers(&p);
        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
                                           &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
        UA_GetEndpointsResponse_deleteMembers(&r);
        break;
    }

    case UA_NS0ID_FINDSERVERSREQUEST: {
        if(clientChannel == &anonymousChannel)
            UA_LOG_DEBUG(server->logger, UA_LOGCATEGORY_NETWORK, "Processing FindServerRequest on Connection %i",
                         connection->sockfd);
        else
            UA_LOG_DEBUG(server->logger, UA_LOGCATEGORY_SECURECHANNEL, "Processing FindServerRequest on SecureChannel %i",
                         clientChannel->securityToken.channelId);
        UA_FindServersRequest  p;
        UA_FindServersResponse r;
        if(UA_FindServersRequest_decodeBinary(msg, pos, &p))
            return;
        UA_FindServersResponse_init(&r);
        init_response_header(&p.requestHeader, &r.responseHeader);
        Service_FindServers(server, &p, &r);
        UA_FindServersRequest_deleteMembers(&p);
        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
                                           &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]);
        UA_FindServersResponse_deleteMembers(&r);
        break;
    }

    case UA_NS0ID_CREATESESSIONREQUEST: {
        UA_CreateSessionRequest  p;
        UA_CreateSessionResponse r;
        if(UA_CreateSessionRequest_decodeBinary(msg, pos, &p))
            return;
        UA_CreateSessionResponse_init(&r);
        init_response_header(&p.requestHeader, &r.responseHeader);
        Service_CreateSession(server, clientChannel, &p, &r);
        UA_CreateSessionRequest_deleteMembers(&p);
        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
                                           &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
        UA_CreateSessionResponse_deleteMembers(&r);
        break;
    }

    case UA_NS0ID_ACTIVATESESSIONREQUEST: {
        UA_ActivateSessionRequest  p;
        UA_ActivateSessionResponse r;
        if(UA_ActivateSessionRequest_decodeBinary(msg, pos, &p))
            return;
        UA_ActivateSessionResponse_init(&r);
        init_response_header(&p.requestHeader, &r.responseHeader);
        Service_ActivateSession(server, clientChannel, &p, &r);
        UA_ActivateSessionRequest_deleteMembers(&p);
        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
                                           &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
        UA_ActivateSessionResponse_deleteMembers(&r);
        break;
    }
    
    case UA_NS0ID_CLOSESESSIONREQUEST:
        INVOKE_SERVICE(CloseSession, UA_TYPES_CLOSESESSIONRESPONSE);
        break;
    case UA_NS0ID_READREQUEST:
        INVOKE_SERVICE(Read, UA_TYPES_READRESPONSE);
        break;
    case UA_NS0ID_WRITEREQUEST:
        INVOKE_SERVICE(Write, UA_TYPES_WRITERESPONSE);
        break;
    case UA_NS0ID_BROWSEREQUEST:
        INVOKE_SERVICE(Browse, UA_TYPES_BROWSERESPONSE);
        break;
    case UA_NS0ID_BROWSENEXTREQUEST:
        INVOKE_SERVICE(BrowseNext, UA_TYPES_BROWSENEXTRESPONSE);
        break;
    case UA_NS0ID_REGISTERNODESREQUEST:
        INVOKE_SERVICE(RegisterNodes, UA_TYPES_REGISTERNODESRESPONSE);
        break;
    case UA_NS0ID_UNREGISTERNODESREQUEST:
        INVOKE_SERVICE(UnregisterNodes, UA_TYPES_UNREGISTERNODESRESPONSE);
        break;
    case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST:
        INVOKE_SERVICE(TranslateBrowsePathsToNodeIds, UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE);
        break;
#ifdef ENABLE_SUBSCRIPTIONS
    case UA_NS0ID_CREATESUBSCRIPTIONREQUEST:
        INVOKE_SERVICE(CreateSubscription, UA_TYPES_CREATESUBSCRIPTIONRESPONSE);
        break;
    case UA_NS0ID_PUBLISHREQUEST:
        INVOKE_SERVICE(Publish, UA_TYPES_PUBLISHRESPONSE);
        break;
    case UA_NS0ID_MODIFYSUBSCRIPTIONREQUEST:
        INVOKE_SERVICE(ModifySubscription, UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE);
        break;
    case UA_NS0ID_DELETESUBSCRIPTIONSREQUEST:
        INVOKE_SERVICE(DeleteSubscriptions, UA_TYPES_DELETESUBSCRIPTIONSRESPONSE);
        break;
    case UA_NS0ID_CREATEMONITOREDITEMSREQUEST:
        INVOKE_SERVICE(CreateMonitoredItems, UA_TYPES_CREATEMONITOREDITEMSRESPONSE);
        break;
    case UA_NS0ID_DELETEMONITOREDITEMSREQUEST:
        INVOKE_SERVICE(DeleteMonitoredItems, UA_TYPES_DELETEMONITOREDITEMSRESPONSE);
        break;
#endif
#ifdef ENABLE_METHODCALLS
    case UA_NS0ID_CALLREQUEST:
        INVOKE_SERVICE(Call, UA_TYPES_CALLRESPONSE);
	break;
#endif
#ifdef ENABLE_NODEMANAGEMENT
    case UA_NS0ID_ADDNODESREQUEST:
        INVOKE_SERVICE(AddNodes, UA_TYPES_ADDNODESRESPONSE);
        break;
    case UA_NS0ID_ADDREFERENCESREQUEST:
        INVOKE_SERVICE(AddReferences, UA_TYPES_ADDREFERENCESRESPONSE);
        break;
    case UA_NS0ID_DELETENODESREQUEST:
        INVOKE_SERVICE(DeleteNodes, UA_TYPES_DELETENODESRESPONSE);
        break;
    case UA_NS0ID_DELETEREFERENCESREQUEST:
        INVOKE_SERVICE(DeleteReferences, UA_TYPES_DELETEREFERENCESRESPONSE);
        break;
#endif
    default: {
        if(requestType.namespaceIndex == 0 && requestType.identifier.numeric==787)
            UA_LOG_INFO(server->logger, UA_LOGCATEGORY_NETWORK,
                        "Client requested a subscription that are not supported, the message will be skipped");
        else
            UA_LOG_INFO(server->logger, UA_LOGCATEGORY_NETWORK, "Unknown request: NodeId(ns=%d, i=%d)",
                        requestType.namespaceIndex, requestType.identifier.numeric);
        UA_RequestHeader p;
        UA_ServiceFault r;
        if(UA_RequestHeader_decodeBinary(msg, pos, &p) != UA_STATUSCODE_GOOD)
            return;
        UA_ServiceFault_init(&r);
        init_response_header(&p, &r.responseHeader);
        r.responseHeader.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
                                           &UA_TYPES[UA_TYPES_SERVICEFAULT]);
        UA_RequestHeader_deleteMembers(&p);
        UA_ServiceFault_deleteMembers(&r);
        break;
    }
    }
}
コード例 #4
0
static void
processMSG(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) {
    /* If we cannot decode these, don't respond */
    UA_UInt32 secureChannelId = 0;
    UA_UInt32 tokenId = 0;
    UA_SequenceHeader sequenceHeader;
    UA_NodeId requestTypeId;
    UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
    retval |= UA_UInt32_decodeBinary(msg, pos, &tokenId);
    retval |= UA_SequenceHeader_decodeBinary(msg, pos, &sequenceHeader);
    retval = UA_NodeId_decodeBinary(msg, pos, &requestTypeId);
    if(retval != UA_STATUSCODE_GOOD)
        return;

    UA_SecureChannel *channel = connection->channel;
    UA_SecureChannel anonymousChannel;
    if(!channel) {
        UA_SecureChannel_init(&anonymousChannel);
        anonymousChannel.connection = connection;
        channel = &anonymousChannel;
    }

    /* Test if the secure channel is ok */
    if(secureChannelId != channel->securityToken.channelId)
        return;
    if(tokenId != channel->securityToken.tokenId) {
        if(tokenId != channel->nextSecurityToken.tokenId) {
            /* close the securechannel but keep the connection open */
            UA_LOG_INFO(server->logger, UA_LOGCATEGORY_SECURECHANNEL,
                        "Request with a wrong security token. Closing the SecureChannel %i.",
                        channel->securityToken.channelId);
            Service_CloseSecureChannel(server, channel->securityToken.channelId);
            return;
        }
        UA_SecureChannel_revolveTokens(channel);
    }

    /* Test if the service type nodeid has the right format */
    if(requestTypeId.identifierType != UA_NODEIDTYPE_NUMERIC ||
       requestTypeId.namespaceIndex != 0) {
        UA_NodeId_deleteMembers(&requestTypeId);
        sendError(channel, msg, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSERVICEUNSUPPORTED);
        return;
    }

    /* Get the service pointers */
    UA_Service service = NULL;
    const UA_DataType *requestType = NULL;
    const UA_DataType *responseType = NULL;
    getServicePointers(requestTypeId.identifier.numeric, &requestType, &responseType, &service);
    if(!service) {
        /* The service is not supported */
        if(requestTypeId.identifier.numeric==787)
            UA_LOG_INFO(server->logger, UA_LOGCATEGORY_SERVER,
                        "Client requested a subscription that are not supported, "
                        "the message will be skipped");
        else
            UA_LOG_INFO(server->logger, UA_LOGCATEGORY_SERVER, "Unknown request: NodeId(ns=%d, i=%d)",
                        requestTypeId.namespaceIndex, requestTypeId.identifier.numeric);
        sendError(channel, msg, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSERVICEUNSUPPORTED);
        return;
    }

    /* Most services can only be called with a valid securechannel */
#ifndef EXTENSION_STATELESS
    if(channel == &anonymousChannel &&
       requestType->typeIndex > UA_TYPES_OPENSECURECHANNELREQUEST) {
        sendError(channel, msg, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSECURECHANNELIDINVALID);
        return;
    }
#endif

    /* Decode the request */
    void *request = UA_alloca(requestType->memSize);
    size_t oldpos = *pos;
    retval = UA_decodeBinary(msg, pos, request, requestType);
    if(retval != UA_STATUSCODE_GOOD) {
        sendError(channel, msg, oldpos, sequenceHeader.requestId, retval);
        return;
    }

    /* Find the matching session */
    UA_Session *session =
        UA_SecureChannel_getSession(channel, &((UA_RequestHeader*)request)->authenticationToken);
    UA_Session anonymousSession;
    if(!session) {
        UA_Session_init(&anonymousSession);
        anonymousSession.channel = channel;
        anonymousSession.activated = UA_TRUE;
        session = &anonymousSession;
    }

    /* Test if the session is valid */
    if(!session->activated && requestType->typeIndex != UA_TYPES_ACTIVATESESSIONREQUEST) {
        UA_LOG_INFO(server->logger, UA_LOGCATEGORY_SERVER, "Client tries to call a service with a non-activated session");
        sendError(channel, msg, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSESSIONNOTACTIVATED);
        return;
    }
#ifndef EXTENSION_STATELESS
    if(session == &anonymousSession &&
       requestType->typeIndex > UA_TYPES_ACTIVATESESSIONREQUEST) {
        UA_LOG_INFO(server->logger, UA_LOGCATEGORY_SERVER, "Client tries to call a service without a session");
        sendError(channel, msg, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSESSIONIDINVALID);
        return;
    }
#endif

    /* Call the service */
    UA_Session_updateLifetime(session);
    void *response = UA_alloca(responseType->memSize);
    UA_init(response, responseType);
    init_response_header(request, response);
    service(server, session, request, response);

    /* Send the response */
    retval = UA_SecureChannel_sendBinaryMessage(channel, sequenceHeader.requestId,
                                                response, responseType);
    if(retval != UA_STATUSCODE_GOOD) {
        /* e.g. UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED */
        sendError(channel, msg, oldpos, sequenceHeader.requestId, retval);
    }

    /* Clean up */
    UA_deleteMembers(request, requestType);
    UA_deleteMembers(response, responseType);
    return;
}