Commit 6df35829 authored by Aurel's avatar Aurel

do more checking to prevent processing of bad messages

parent 3c10448d
...@@ -33,7 +33,8 @@ from Products.PluggableAuthService.interfaces.plugins import \ ...@@ -33,7 +33,8 @@ from Products.PluggableAuthService.interfaces.plugins import \
from Products.ERP5SyncML.XMLSyncUtils import resolveSyncmlStatusCode, decode from Products.ERP5SyncML.XMLSyncUtils import resolveSyncmlStatusCode, decode
from Products.ERP5SyncML.SyncMLMessage import SyncMLResponse from Products.ERP5SyncML.SyncMLMessage import SyncMLResponse
from Products.ERP5SyncML.SyncMLConstant import NULL_ANCHOR, ACTIVITY_PRIORITY from Products.ERP5SyncML.SyncMLConstant import NULL_ANCHOR, ACTIVITY_PRIORITY, \
SynchronizationError
syncml_logger = getLogger('ERP5SyncML') syncml_logger = getLogger('ERP5SyncML')
...@@ -64,6 +65,9 @@ class EngineMixin(object): ...@@ -64,6 +65,9 @@ class EngineMixin(object):
sync_status_counter = 0 sync_status_counter = 0
for status in syncml_request.status_list: for status in syncml_request.status_list:
if status["command"] == "SyncHdr": # Check for authentication if status["command"] == "SyncHdr": # Check for authentication
if domain.getSynchronizationState() != "initializing":
raise SynchronizationError(
"Authentication header found although it is already done")
if status['status_code'] == \ if status['status_code'] == \
resolveSyncmlStatusCode('missing_credentials'): resolveSyncmlStatusCode('missing_credentials'):
# Server challenged an authentication # Server challenged an authentication
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from logging import getLogger from logging import getLogger
from Products.ERP5SyncML.Engine.EngineMixin import EngineMixin from Products.ERP5SyncML.Engine.EngineMixin import EngineMixin
from Products.ERP5SyncML.SyncMLConstant import SynchronizationError
syncml_logger = getLogger('ERP5SyncML') syncml_logger = getLogger('ERP5SyncML')
...@@ -57,7 +57,13 @@ class SyncMLSynchronousEngine(EngineMixin): ...@@ -57,7 +57,13 @@ class SyncMLSynchronousEngine(EngineMixin):
syncml_response = self._generateBaseResponse(subscription) syncml_response = self._generateBaseResponse(subscription)
# Read & apply status about databases & synchronizations # Read & apply status about databases & synchronizations
self._readStatusList(syncml_request, subscription, syncml_response) try:
self._readStatusList(syncml_request, subscription, syncml_response)
except SynchronizationError:
# Looks like we process an already received message
syncml_logger.error("%s does no process packet due to error"
% (subscription.getRelativeUrl()))
return
if syncml_request.isFinal and \ if syncml_request.isFinal and \
subscription.getSynchronizationState() == "initializing": subscription.getSynchronizationState() == "initializing":
...@@ -148,11 +154,14 @@ class SyncMLSynchronousEngine(EngineMixin): ...@@ -148,11 +154,14 @@ class SyncMLSynchronousEngine(EngineMixin):
# Apply status about object send & synchronized if any # Apply status about object send & synchronized if any
self._readStatusList(syncml_request, subscriber, syncml_response, True) self._readStatusList(syncml_request, subscriber, syncml_response, True)
if syncml_request.isFinal and \ if syncml_request.isFinal:
subscriber.getSynchronizationState() == \ if subscriber.getSynchronizationState() == \
"sending_modifications": "waiting_notifications":
# We got the last notifications from clients # We got the last notifications from clients
subscriber.finish() subscriber.finish()
elif subscriber.getSynchronizationState() != \
"processing_sync_requests":
raise SynchronizationError("Got final request although not waiting for it")
# XXX We compute gid list so that we do not get issue with catalog # XXX We compute gid list so that we do not get issue with catalog
# XXX This is a hack, if real datasynchronization is implemented # XXX This is a hack, if real datasynchronization is implemented
...@@ -202,6 +211,7 @@ class SyncMLSynchronousEngine(EngineMixin): ...@@ -202,6 +211,7 @@ class SyncMLSynchronousEngine(EngineMixin):
if finished: if finished:
subscriber._getDeletedData(syncml_response=syncml_response) subscriber._getDeletedData(syncml_response=syncml_response)
syncml_response.addFinal() syncml_response.addFinal()
subscriber.waitNotifications()
# Do not go into finished here as we must wait for # Do not go into finished here as we must wait for
# notifications from client # notifications from client
if subscriber.getSynchronizationState() == "finished": if subscriber.getSynchronizationState() == "finished":
......
...@@ -99,3 +99,5 @@ REPLACE_ACTION = 'Replace' ...@@ -99,3 +99,5 @@ REPLACE_ACTION = 'Replace'
ACTIVITY_PRIORITY = 5 ACTIVITY_PRIORITY = 5
class SynchronizationError(Exception):
pass
...@@ -34,7 +34,8 @@ from AccessControl import ClassSecurityInfo ...@@ -34,7 +34,8 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type.Tool.BaseTool import BaseTool from Products.ERP5Type.Tool.BaseTool import BaseTool
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5Type.Globals import InitializeClass from Products.ERP5Type.Globals import InitializeClass
from Products.ERP5SyncML.SyncMLConstant import ACTIVITY_PRIORITY from Products.ERP5SyncML.SyncMLConstant import ACTIVITY_PRIORITY, \
SynchronizationError
from Products.ERP5SyncML.SyncMLMessage import SyncMLResponse, SyncMLRequest from Products.ERP5SyncML.SyncMLMessage import SyncMLResponse, SyncMLRequest
from Products.ERP5SyncML.Engine.SynchronousEngine import SyncMLSynchronousEngine from Products.ERP5SyncML.Engine.SynchronousEngine import SyncMLSynchronousEngine
from Products.ERP5SyncML.Engine.AsynchronousEngine import SyncMLAsynchronousEngine from Products.ERP5SyncML.Engine.AsynchronousEngine import SyncMLAsynchronousEngine
...@@ -319,6 +320,13 @@ class SynchronizationTool(BaseTool): ...@@ -319,6 +320,13 @@ class SynchronizationTool(BaseTool):
assert len(database_alert_list) <= 1, "Multi-databases sync no supported" assert len(database_alert_list) <= 1, "Multi-databases sync no supported"
if len(database_alert_list): if len(database_alert_list):
# We are initializing the synchronization # We are initializing the synchronization
if subscriber and subscriber.getSynchronizationState() not in \
("not_running", "finished"):
syncml_logger.error(
'Trying to start a synchronization on server side : %s although synchronisation is already running'
% (subscriber.getPath(),))
# Prevent initilisation if sync already running
return
syncml_response = engine.processServerInitialization( syncml_response = engine.processServerInitialization(
publication=publication, publication=publication,
syncml_request=syncml_request, syncml_request=syncml_request,
...@@ -329,7 +337,10 @@ class SynchronizationTool(BaseTool): ...@@ -329,7 +337,10 @@ class SynchronizationTool(BaseTool):
raise ValueError("First synchronization message must contains alert command") raise ValueError("First synchronization message must contains alert command")
else: else:
# Let engine manage the synchronization # Let engine manage the synchronization
return engine.processServerSynchronization(subscriber, syncml_request) try:
return engine.processServerSynchronization(subscriber, syncml_request)
except SynchronizationError:
return
else: else:
# This must be implemented following the syncml protocol, not with this hack # This must be implemented following the syncml protocol, not with this hack
raise NotImplementedError("Starting sync process from server is forbidden") raise NotImplementedError("Starting sync process from server is forbidden")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment