void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) { if(channel == NULL) { response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; return; } if(channel->connection == NULL) { response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; return; } UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Trying to create session"); if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN || channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { if(!UA_ByteString_equal(&request->clientCertificate, &channel->remoteCertificate)) { response->responseHeader.serviceResult = UA_STATUSCODE_BADCERTIFICATEINVALID; return; } } if(channel->securityToken.channelId == 0) { response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURECHANNELIDINVALID; return; } if(!UA_ByteString_equal(&channel->securityPolicy->policyUri, &UA_SECURITY_POLICY_NONE_URI) && request->clientNonce.length < 32) { response->responseHeader.serviceResult = UA_STATUSCODE_BADNONCEINVALID; return; } ////////////////////// TODO: Compare application URI with certificate uri (decode certificate) /* Allocate the response */ response->serverEndpoints = (UA_EndpointDescription*) UA_Array_new(server->config.endpointsSize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); if(!response->serverEndpoints) { response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; return; } response->serverEndpointsSize = server->config.endpointsSize; /* Copy the server's endpointdescriptions into the response */ for(size_t i = 0; i < server->config.endpointsSize; ++i) response->responseHeader.serviceResult |= UA_EndpointDescription_copy(&server->config.endpoints[0].endpointDescription, &response->serverEndpoints[i]); if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) return; /* Mirror back the endpointUrl */ for(size_t i = 0; i < response->serverEndpointsSize; ++i) { UA_String_deleteMembers(&response->serverEndpoints[i].endpointUrl); UA_String_copy(&request->endpointUrl, &response->serverEndpoints[i].endpointUrl); } UA_Session *newSession; response->responseHeader.serviceResult = UA_SessionManager_createSession(&server->sessionManager, channel, request, &newSession); if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Processing CreateSessionRequest failed"); return; } /* Fill the session with more information */ newSession->maxResponseMessageSize = request->maxResponseMessageSize; newSession->maxRequestMessageSize = channel->connection->localConf.maxMessageSize; response->responseHeader.serviceResult |= UA_ApplicationDescription_copy(&request->clientDescription, &newSession->clientDescription); /* Prepare the response */ response->sessionId = newSession->sessionId; response->revisedSessionTimeout = (UA_Double)newSession->timeout; response->authenticationToken = newSession->authenticationToken; response->responseHeader.serviceResult = UA_String_copy(&request->sessionName, &newSession->sessionName); if(server->config.endpointsSize > 0) response->responseHeader.serviceResult |= UA_ByteString_copy(&channel->securityPolicy->localCertificate, &response->serverCertificate); /* Create a signed nonce */ response->responseHeader.serviceResult = nonceAndSignCreateSessionResponse(server, channel, newSession, request, response); /* Failure -> remove the session */ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { UA_SessionManager_removeSession(&server->sessionManager, &newSession->authenticationToken); return; } UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Session " UA_PRINTF_GUID_FORMAT " created", UA_PRINTF_GUID_DATA(newSession->sessionId.identifier.guid)); }
void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) { if(channel->securityToken.channelId == 0) { response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURECHANNELIDINVALID; return; } /* Allocate the response */ response->serverEndpoints = (UA_EndpointDescription*) UA_Array_new(server->config.endpoints.count, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); if(!response->serverEndpoints) { response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; return; } response->serverEndpointsSize = server->config.endpoints.count; /* Copy the server's endpointdescriptions into the response */ for(size_t i = 0; i < server->config.endpoints.count; ++i) response->responseHeader.serviceResult |= UA_EndpointDescription_copy(&server->config.endpoints.endpoints[0].endpointDescription, &response->serverEndpoints[i]); /* Mirror back the endpointUrl */ for(size_t i = 0; i < response->serverEndpointsSize; ++i) { UA_String_deleteMembers(&response->serverEndpoints[i].endpointUrl); UA_String_copy(&request->endpointUrl, &response->serverEndpoints[i].endpointUrl); } UA_Session *newSession; response->responseHeader.serviceResult = UA_SessionManager_createSession(&server->sessionManager, channel, request, &newSession); if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Processing CreateSessionRequest failed"); return; } /* Fill the session with more information */ newSession->maxResponseMessageSize = request->maxResponseMessageSize; newSession->maxRequestMessageSize = channel->connection->localConf.maxMessageSize; response->responseHeader.serviceResult |= UA_ApplicationDescription_copy(&request->clientDescription, &newSession->clientDescription); /* Prepare the response */ response->sessionId = newSession->sessionId; response->revisedSessionTimeout = (UA_Double)newSession->timeout; response->authenticationToken = newSession->authenticationToken; response->responseHeader.serviceResult = UA_String_copy(&request->sessionName, &newSession->sessionName); if(server->config.endpoints.count > 0) response->responseHeader.serviceResult |= UA_ByteString_copy(&server->config.endpoints.endpoints[0].endpointDescription.serverCertificate, &response->serverCertificate); /* Failure -> remove the session */ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { UA_SessionManager_removeSession(&server->sessionManager, &newSession->authenticationToken); return; } UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Session " UA_PRINTF_GUID_FORMAT " created", UA_PRINTF_GUID_DATA(newSession->sessionId.identifier.guid)); }
UA_StatusCode UA_NodeId_toString(const UA_NodeId *nodeId, UA_String *nodeIdStr) { if (nodeIdStr->length != 0) { UA_free(nodeIdStr->data); nodeIdStr->data = NULL; nodeIdStr->length = 0; } if (nodeId == NULL) return UA_STATUSCODE_GOOD; char *nsStr = NULL; long snprintfLen = 0; size_t nsLen = 0; if (nodeId->namespaceIndex != 0) { nsStr = (char*)UA_malloc(9+1); // strlen("ns=XXXXX;") = 9 + Nullbyte snprintfLen = UA_snprintf(nsStr, 10, "ns=%d;", nodeId->namespaceIndex); if (snprintfLen < 0 || snprintfLen >= 10) { UA_free(nsStr); return UA_STATUSCODE_BADINTERNALERROR; } nsLen = (size_t)(snprintfLen); } UA_ByteString byteStr = UA_BYTESTRING_NULL; switch (nodeId->identifierType) { case UA_NODEIDTYPE_NUMERIC: /* ns (2 byte, 65535) = 5 chars, numeric (4 byte, 4294967295) = 10 chars, delim = 1 , nullbyte = 1-> 17 chars */ nodeIdStr->length = nsLen + 2 + 10 + 1; nodeIdStr->data = (UA_Byte*)UA_malloc(nodeIdStr->length); if (nodeIdStr->data == NULL) { nodeIdStr->length = 0; UA_free(nsStr); return UA_STATUSCODE_BADOUTOFMEMORY; } snprintfLen =UA_snprintf((char*)nodeIdStr->data, nodeIdStr->length, "%si=%lu", nsLen > 0 ? nsStr : "", (unsigned long )nodeId->identifier.numeric); break; case UA_NODEIDTYPE_STRING: /* ns (16bit) = 5 chars, strlen + nullbyte */ nodeIdStr->length = nsLen + 2 + nodeId->identifier.string.length + 1; nodeIdStr->data = (UA_Byte*)UA_malloc(nodeIdStr->length); if (nodeIdStr->data == NULL) { nodeIdStr->length = 0; UA_free(nsStr); return UA_STATUSCODE_BADOUTOFMEMORY; } snprintfLen =UA_snprintf((char*)nodeIdStr->data, nodeIdStr->length, "%ss=%.*s", nsLen > 0 ? nsStr : "", (int)nodeId->identifier.string.length, nodeId->identifier.string.data); break; case UA_NODEIDTYPE_GUID: /* ns (16bit) = 5 chars + strlen(A123456C-0ABC-1A2B-815F-687212AAEE1B)=36 + nullbyte */ nodeIdStr->length = nsLen + 2 + 36 + 1; nodeIdStr->data = (UA_Byte*)UA_malloc(nodeIdStr->length); if (nodeIdStr->data == NULL) { nodeIdStr->length = 0; UA_free(nsStr); return UA_STATUSCODE_BADOUTOFMEMORY; } snprintfLen = UA_snprintf((char*)nodeIdStr->data, nodeIdStr->length, "%sg=" UA_PRINTF_GUID_FORMAT, nsLen > 0 ? nsStr : "", UA_PRINTF_GUID_DATA(nodeId->identifier.guid)); break; case UA_NODEIDTYPE_BYTESTRING: UA_ByteString_toBase64String(&nodeId->identifier.byteString, &byteStr); /* ns (16bit) = 5 chars + LEN + nullbyte */ nodeIdStr->length = nsLen + 2 + byteStr.length + 1; nodeIdStr->data = (UA_Byte*)UA_malloc(nodeIdStr->length); if (nodeIdStr->data == NULL) { nodeIdStr->length = 0; UA_String_deleteMembers(&byteStr); UA_free(nsStr); return UA_STATUSCODE_BADOUTOFMEMORY; } snprintfLen = UA_snprintf((char*)nodeIdStr->data, nodeIdStr->length, "%sb=%.*s", nsLen > 0 ? nsStr : "", (int)byteStr.length, byteStr.data); UA_String_deleteMembers(&byteStr); break; } UA_free(nsStr); if (snprintfLen < 0 || snprintfLen >= (long) nodeIdStr->length) { UA_free(nodeIdStr->data); nodeIdStr->data = NULL; nodeIdStr->length = 0; return UA_STATUSCODE_BADINTERNALERROR; } nodeIdStr->length = (size_t)snprintfLen; return UA_STATUSCODE_GOOD; }