Revision: 3577 http://trac.macosforge.org/projects/calendarserver/changeset/3577 Author: sagen@apple.com Date: 2009-01-07 14:54:17 -0800 (Wed, 07 Jan 2009) Log Message: ----------- Support for retrieving xmpp and email passwords from system keychain Modified Paths: -------------- CalendarServer/trunk/twistedcaldav/config.py CalendarServer/trunk/twistedcaldav/util.py Modified: CalendarServer/trunk/twistedcaldav/config.py =================================================================== --- CalendarServer/trunk/twistedcaldav/config.py 2009-01-07 21:51:22 UTC (rev 3576) +++ CalendarServer/trunk/twistedcaldav/config.py 2009-01-07 22:54:17 UTC (rev 3577) @@ -34,6 +34,9 @@ from twistedcaldav.log import Logger from twistedcaldav.log import clearLogLevels, setLogLevelForNamespace, InvalidLogLevelError +from twistedcaldav.util import ( + KeychainAccessError, KeychainPasswordNotFound, getPasswordFromKeychain +) log = Logger() @@ -418,6 +421,7 @@ self.updateDropBox, self.updateLogLevels, self.updateNotifications, + self.updateScheduling, ] def __str__(self): @@ -638,11 +642,50 @@ service["Service"] == "twistedcaldav.notify.XMPPNotifierService" and service["Enabled"] ): + # Get password from keychain. If not there, fall back to what + # is in the plist. + try: + password = getPasswordFromKeychain("icalserver.xmpp") + service["Password"] = password + log.info("XMPP password successfully retreived from keychain") + except KeychainAccessError: + # The system doesn't support keychain + pass + except KeychainPasswordNotFound: + # The password doesn't exist in the keychain. + log.error("XMPP password not found in keychain") + + # Check for empty fields for key, value in service.iteritems(): if not value and key not in ("AllowedJIDs", "HeartbeatMinutes"): raise ConfigurationError("Invalid %s for XMPPNotifierService: %r" % (key, value)) + @staticmethod + def updateScheduling(self, items): + # + # Scheduling + # + service = self.Scheduling["iMIP"] + + if service["Enabled"]: + for direction in ("Sending", "Receiving"): + # Get password from keychain. If not there, fall back to what + # is in the plist. Keychain account names are icalserver.sending + # and icalserver.receiving. + try: + account = "icalserver.%s" % (direction.lower(),) + password = getPasswordFromKeychain(account) + service[direction]["Password"] = password + log.info("iMIP %s password successfully retreived from keychain" % (direction,)) + except KeychainAccessError: + # The system doesn't support keychain + pass + except KeychainPasswordNotFound: + # The password doesn't exist in the keychain. + log.info("iMIP %s password not found in keychain" % (direction,)) + + def _mergeData(oldData, newData): for key, value in newData.iteritems(): if isinstance(value, (dict,)): Modified: CalendarServer/trunk/twistedcaldav/util.py =================================================================== --- CalendarServer/trunk/twistedcaldav/util.py 2009-01-07 21:51:22 UTC (rev 3576) +++ CalendarServer/trunk/twistedcaldav/util.py 2009-01-07 22:54:17 UTC (rev 3577) @@ -14,7 +14,10 @@ # limitations under the License. ## +import os +import re import sys +from subprocess import Popen, PIPE, STDOUT ## # getNCPU @@ -117,3 +120,44 @@ if isinstance(s, unicode): s = s.encode("utf-8") return s + +## +# Keychain access +## + +class KeychainPasswordNotFound(Exception): + """ + Exception raised when the password does not exist + """ + +class KeychainAccessError(Exception): + """ + Exception raised when not able to access keychain + """ + +passwordRegExp = re.compile(r'password: "(.*)"') + +def getPasswordFromKeychain(account): + if os.path.isfile("/usr/bin/security"): + child = Popen( + args=[ + "/usr/bin/security", "find-generic-password", + "-a", account, "-g", + ], + stdout=PIPE, stderr=STDOUT, + ) + output, error = child.communicate() + + if child.returncode: + raise KeychainPasswordNotFound(error) + else: + match = passwordRegExp.search(output) + if not match: + error = "Password for %s not found in keychain" % (account,) + raise KeychainPasswordNotFound(error) + else: + return match.group(1) + + else: + error = "Keychain access utility ('security') not found" + raise KeychainAccessError(error)
participants (1)
-
source_changes@macosforge.org