[CalendarServer-changes] [15323] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Nov 16 12:14:08 PST 2015


Revision: 15323
          http://trac.calendarserver.org//changeset/15323
Author:   sagen at apple.com
Date:     2015-11-16 12:14:08 -0800 (Mon, 16 Nov 2015)
Log Message:
-----------
Post an alert when imap cert is untrusted

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/tap/test/test_util.py
    CalendarServer/trunk/calendarserver/tap/util.py
    CalendarServer/trunk/calendarserver/tools/util.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/inbound.py

Modified: CalendarServer/trunk/calendarserver/tap/test/test_util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/test/test_util.py	2015-11-16 20:12:59 UTC (rev 15322)
+++ CalendarServer/trunk/calendarserver/tap/test/test_util.py	2015-11-16 20:14:08 UTC (rev 15323)
@@ -14,7 +14,10 @@
 # limitations under the License.
 ##
 
-from calendarserver.tap.util import MemoryLimitService, Stepper, verifyTLSCertificate, memoryForPID
+from calendarserver.tap.util import (
+    MemoryLimitService, Stepper, verifyTLSCertificate, memoryForPID,
+    secondsSinceLastPost, recordTimeStamp
+)
 
 from twisted.internet.defer import succeed, inlineCallbacks
 from twisted.internet.task import Clock
@@ -296,3 +299,40 @@
             )
         )
         self.assertFalse(success)
+
+
+class AlertTestCase(TestCase):
+
+    def test_secondsSinceLastPost(self):
+
+        timestampsDir = self.mktemp()
+        os.mkdir(timestampsDir)
+
+        # Non existent timestamp file
+        self.assertEquals(
+            secondsSinceLastPost("TestAlert", timestampsDirectory=timestampsDir, now=10),
+            10
+        )
+
+        # Existing valid, past timestamp file
+        recordTimeStamp("TestAlert", timestampsDirectory=timestampsDir, now=5)
+        self.assertEquals(
+            secondsSinceLastPost("TestAlert", timestampsDirectory=timestampsDir, now=12),
+            7
+        )
+
+        # Existing valid, future timestamp file
+        recordTimeStamp("TestAlert", timestampsDirectory=timestampsDir, now=20)
+        self.assertEquals(
+            secondsSinceLastPost("TestAlert", timestampsDirectory=timestampsDir, now=12),
+            -8
+        )
+
+        # Existing invalid timestamp file
+        dirFP = FilePath(timestampsDir)
+        child = dirFP.child(".TestAlert.timestamp")
+        child.setContent("not a number")
+        self.assertEquals(
+            secondsSinceLastPost("TestAlert", timestampsDirectory=timestampsDir, now=12),
+            12
+        )

Modified: CalendarServer/trunk/calendarserver/tap/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/util.py	2015-11-16 20:12:59 UTC (rev 15322)
+++ CalendarServer/trunk/calendarserver/tap/util.py	2015-11-16 20:14:08 UTC (rev 15323)
@@ -111,6 +111,7 @@
 import os
 import psutil
 import sys
+import time
 
 try:
     from twistedcaldav.authkerb import NegotiateCredentialFactory
@@ -1325,7 +1326,7 @@
                         cert=config.SSLCertificate
                     )
                 )
-                postAlert("MissingCertificateAlert", ["path", config.SSLCertificate])
+                postAlert("MissingCertificateAlert", 0, ["path", config.SSLCertificate])
                 return False, message
 
             length = os.stat(config.SSLCertificate).st_size
@@ -1392,7 +1393,7 @@
                         topic = getAPNTopicFromIdentity(protoConfig.KeychainIdentity)
                         protoConfig.Topic = topic
                     if not protoConfig.Topic:
-                        postAlert("PushNotificationKeychainIdentityAlert", [])
+                        postAlert("PushNotificationKeychainIdentityAlert", 0, [])
                         message = "Cannot extract APN topic"
                         return False, message
 
@@ -1415,7 +1416,7 @@
                             proto=protocol,
                         )
                     )
-                    postAlert("MissingKeychainIdentityAlert", [])
+                    postAlert("MissingKeychainIdentityAlert", 0, [])
                     return False, message
 
             else:
@@ -1426,7 +1427,7 @@
                             cert=protoConfig.CertificatePath
                         )
                     )
-                    postAlert("PushNotificationCertificateAlert", [])
+                    postAlert("PushNotificationCertificateAlert", 0, [])
                     return False, message
 
                 # Verify we can extract the topic
@@ -1434,7 +1435,7 @@
                     topic = getAPNTopicFromCertificate(protoConfig.CertificatePath)
                     protoConfig.Topic = topic
                 if not protoConfig.Topic:
-                    postAlert("PushNotificationCertificateAlert", [])
+                    postAlert("PushNotificationCertificateAlert", 0, [])
                     message = "Cannot extract APN topic"
                     return False, message
 
@@ -1448,7 +1449,7 @@
                         pass
                     except KeychainPasswordNotFound:
                         # The password doesn't exist in the keychain.
-                        postAlert("PushNotificationCertificateAlert", [])
+                        postAlert("PushNotificationCertificateAlert", 0, [])
                         message = "Cannot retrieve APN passphrase from keychain"
                         return False, message
 
@@ -1484,7 +1485,7 @@
                             reason=str(e)
                         )
                     )
-                postAlert("PushNotificationCertificateAlert", [])
+                postAlert("PushNotificationCertificateAlert", 0, [])
                 return False, message
 
         return True, "APNS enabled"
@@ -1562,11 +1563,51 @@
 
 
 
-def postAlert(alertType, args):
+def secondsSinceLastPost(alertType, timestampsDirectory=None, now=None):
+    if timestampsDirectory is None:
+        timestampsDirectory = config.DataRoot
+    if now is None:
+        now = int(time.time())
+
+    dirFP = FilePath(timestampsDirectory)
+    childFP = dirFP.child(".{}.timestamp".format(alertType))
+    if not childFP.exists():
+        timestamp = 0
+    else:
+        with childFP.open() as child:
+            try:
+                line = child.readline().strip()
+                timestamp = int(line)
+            except:
+                timestamp = 0
+    return now - timestamp
+
+
+
+def recordTimeStamp(alertType, timestampsDirectory=None, now=None):
+    if timestampsDirectory is None:
+        timestampsDirectory = config.DataRoot
+    if now is None:
+        now = int(time.time())
+
+    dirFP = FilePath(timestampsDirectory)
+    childFP = dirFP.child(".{}.timestamp".format(alertType))
+    childFP.setContent(str(now))
+
+
+
+def postAlert(alertType, ignoreWithinSeconds, args):
     if (
         config.AlertPostingProgram and
         os.path.exists(config.AlertPostingProgram)
     ):
+        if ignoreWithinSeconds:
+            seconds = secondsSinceLastPost(alertType)
+            if seconds < ignoreWithinSeconds:
+                return
+
+        recordTimeStamp(alertType)
+
         try:
             commandLine = [config.AlertPostingProgram, alertType]
             commandLine.extend(args)

Modified: CalendarServer/trunk/calendarserver/tools/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/util.py	2015-11-16 20:12:59 UTC (rev 15322)
+++ CalendarServer/trunk/calendarserver/tools/util.py	2015-11-16 20:14:08 UTC (rev 15323)
@@ -150,7 +150,7 @@
             # until the volume is mounted
             if not os.path.exists(dirpath) or (diagnose.detectPhantomVolume(dirpath) == diagnose.EXIT_CODE_PHANTOM_DATA_VOLUME):
                 from calendarserver.tap.util import postAlert
-                postAlert("MissingDataVolumeAlert", ["volumePath", dirpath])
+                postAlert("MissingDataVolumeAlert", 0, ["volumePath", dirpath])
 
             while not os.path.exists(dirpath) or (diagnose.detectPhantomVolume(dirpath) == diagnose.EXIT_CODE_PHANTOM_DATA_VOLUME):
                 if not os.path.exists(dirpath):

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/inbound.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/inbound.py	2015-11-16 20:12:59 UTC (rev 15322)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/inbound.py	2015-11-16 20:14:08 UTC (rev 15323)
@@ -42,6 +42,8 @@
 import dateutil.tz
 import email.utils
 
+from OpenSSL.SSL import Error as TLSError
+from calendarserver.tap.util import postAlert
 
 log = Logger()
 
@@ -635,6 +637,12 @@
 class IMAP4DownloadProtocol(imap4.IMAP4Client):
     log = Logger()
 
+
+    def connectionLost(self, reason):
+        if reason.type is TLSError:
+            postAlert("MailCertificateAlert", 7 * 24 * 60 * 60, [])
+
+
     def serverGreeting(self, capabilities):
         self.log.debug("IMAP servergreeting")
         return self.authenticate(
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20151116/1414521f/attachment-0001.html>


More information about the calendarserver-changes mailing list