[CalendarServer-changes] [2157] CalendarServer/trunk/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Mon Feb 18 14:04:42 PST 2008
Revision: 2157
http://trac.macosforge.org/projects/calendarserver/changeset/2157
Author: wsanchez at apple.com
Date: 2008-02-18 14:04:41 -0800 (Mon, 18 Feb 2008)
Log Message:
-----------
Merge source:CalendarServer/branches/getsslpassphrase.
Fixes #221
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/config.py
CalendarServer/trunk/twistedcaldav/tap.py
Modified: CalendarServer/trunk/twistedcaldav/config.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/config.py 2008-02-18 22:03:03 UTC (rev 2156)
+++ CalendarServer/trunk/twistedcaldav/config.py 2008-02-18 22:04:41 UTC (rev 2157)
@@ -116,6 +116,7 @@
"SSLCertificate": "/etc/certificates/Default.crt", # Public key
"SSLPrivateKey": "/etc/certificates/Default.key", # Private key
"SSLAuthorityChain": "", # Certificate Authority Chain
+ "SSLPassPhraseDialog": "/etc/apache2/getsslpassphrase",
#
# Process management
Modified: CalendarServer/trunk/twistedcaldav/tap.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/tap.py 2008-02-18 22:03:03 UTC (rev 2156)
+++ CalendarServer/trunk/twistedcaldav/tap.py 2008-02-18 22:04:41 UTC (rev 2157)
@@ -99,7 +99,9 @@
value = value.split(',')
elif isinstance(configDict[key], dict):
- raise UsageError("Dict options not supported on the command line")
+ raise UsageError(
+ "Dict options not supported on the command line"
+ )
elif value == 'None':
value = None
@@ -119,13 +121,16 @@
if key in configDict:
if not isinstance(configDict[key], dict):
raise UsageError(
- "Found intermediate path element that is not a dictionary")
+ "Found intermediate path element that is not a dictionary"
+ )
if key not in overrideDict:
overrideDict[key] = {}
self._setOverride(
- configDict[key], path[1:], value, overrideDict[key])
+ configDict[key], path[1:],
+ value, overrideDict[key]
+ )
def opt_option(self, option):
"""
@@ -135,10 +140,14 @@
--option flags may be specified.
"""
- if '=' in option:
+ if "=" in option:
path, value = option.split('=')
self._setOverride(
- defaultConfig, path.split('/'), value, self.overrides)
+ defaultConfig,
+ path.split('/'),
+ value,
+ self.overrides
+ )
else:
self.opt_option('%s=True' % (option,))
@@ -146,8 +155,8 @@
def postOptions(self):
if not os.path.exists(self['config']):
- log.msg("Config file %s not found, using defaults" % (
- self['config'],))
+ log.msg("Config file %s not found, using defaults"
+ % (self['config'],))
parseConfig(self['config'])
@@ -188,7 +197,7 @@
access=os.W_OK,
#permissions=0750,
#uname=config.UserName,
- #gname=config.GroupName
+ #gname=config.GroupName,
)
# Verify that data root actually exists
@@ -198,8 +207,8 @@
access=os.W_OK,
#permissions=0750,
#uname=config.UserName,
- #gname=config.GroupName
- create=(0750, config.UserName, config.GroupName,)
+ #gname=config.GroupName,
+ create=(0750, config.UserName, config.GroupName,),
)
# Verify that ssl certs exist if needed
@@ -209,13 +218,13 @@
config.SSLPrivateKey,
"SSL Private key",
access=os.R_OK,
- #permissions=0640
+ #permissions=0640,
)
self.checkFile(
config.SSLCertificate,
"SSL Public key",
access=os.R_OK,
- #permissions=0644
+ #permissions=0644,
)
except ConfigurationError, e:
log.err(str(e))
@@ -226,16 +235,20 @@
# Nuke the file log observer's time format.
#
- if not config.ErrorLogFile and config.ProcessType == 'Slave':
- log.FileLogObserver.timeFormat = ''
+ if not config.ErrorLogFile and config.ProcessType == "Slave":
+ log.FileLogObserver.timeFormat = ""
# Check current umask and warn if changed
oldmask = os.umask(config.umask)
if oldmask != config.umask:
- log.msg("WARNING: changing umask from: 0%03o to 0%03o" % (
- oldmask, config.umask,))
+ log.msg("WARNING: changing umask from: 0%03o to 0%03o"
+ % (oldmask, config.umask,))
- def checkDirectory(self, dirpath, description, access=None, fail=False, permissions=None, uname=None, gname=None, create=None):
+ def checkDirectory(
+ self, dirpath, description,
+ access=None, fail=False, permissions=None,
+ uname=None, gname=None, create=None
+ ):
if not os.path.exists(dirpath):
if create is not None:
# create is a tuple of (mode, username, groupname)
@@ -250,30 +263,63 @@
os.chown(dirpath, uid, gid)
except:
log.msg("Could not create %s" % (dirpath,))
- raise ConfigurationError("%s does not exist and cannot be created: %s" % (description, dirpath,))
+ raise ConfigurationError(
+ "%s does not exist and cannot be created: %s"
+ % (description, dirpath,)
+ )
log.msg("Created %s" % (dirpath,))
else:
- raise ConfigurationError("%s does not exist: %s" % (description, dirpath,))
+ raise ConfigurationError("%s does not exist: %s"
+ % (description, dirpath,))
if not os.path.isdir(dirpath):
- raise ConfigurationError("%s is not a directory: %s" % (description, dirpath,))
+ raise ConfigurationError("%s is not a directory: %s"
+ % (description, dirpath,))
if access and not os.access(dirpath, access):
- raise ConfigurationError("Insufficient permissions for server on %s directory: %s" % (description, dirpath,))
+ raise ConfigurationError(
+ "Insufficient permissions for server on %s directory: %s"
+ % (description, dirpath,)
+ )
- self.securityCheck(dirpath, description, fail=fail, permissions=permissions, uname=uname, gname=gname)
+ self.securityCheck(
+ dirpath, description,
+ fail=fail, permissions=permissions,
+ uname=uname, gname=gname
+ )
- def checkFile(self, filepath, description, access=None, fail=False, permissions=None, uname=None, gname=None):
+ def checkFile(
+ self, filepath, description,
+ access=None, fail=False, permissions=None,
+ uname=None, gname=None
+ ):
if not os.path.exists(filepath):
- raise ConfigurationError("%s does not exist: %s" % (description, filepath,))
+ raise ConfigurationError(
+ "%s does not exist: %s"
+ % (description, filepath,)
+ )
elif not os.path.isfile(filepath):
- raise ConfigurationError("%s is not a file: %s" % (description, filepath,))
+ raise ConfigurationError(
+ "%s is not a file: %s"
+ % (description, filepath,)
+ )
elif access and not os.access(filepath, access):
- raise ConfigurationError("Insufficient permissions for server on %s directory: %s" % (description, filepath,))
- self.securityCheck(filepath, description, fail=fail, permissions=permissions, uname=uname, gname=gname)
+ raise ConfigurationError(
+ "Insufficient permissions for server on %s directory: %s"
+ % (description, filepath,)
+ )
+ self.securityCheck(
+ filepath, description,
+ fail=fail, permissions=permissions,
+ uname=uname, gname=gname
+ )
- def securityCheck(self, path, description, fail=False, permissions=None, uname=None, gname=None):
+ def securityCheck(
+ self, path, description,
+ fail=False, permissions=None,
+ uname=None, gname=None
+ ):
def raiseOrPrint(txt):
if fail:
raise ConfigurationError(txt)
@@ -283,50 +329,109 @@
pathstat = os.stat(path)
if permissions:
if stat.S_IMODE(pathstat[stat.ST_MODE]) != permissions:
- raiseOrPrint("The permisions on %s directory %s are 0%03o and do not match expected permissions: 0%03o"
- % (description, path, stat.S_IMODE(pathstat[stat.ST_MODE]), permissions))
+ raiseOrPrint(
+ "The permisions on %s directory %s are 0%03o "
+ "and do not match expected permissions: 0%03o"
+ % (description, path,
+ stat.S_IMODE(pathstat[stat.ST_MODE]), permissions)
+ )
if uname:
import pwd
try:
pathuname = pwd.getpwuid(pathstat[stat.ST_UID])[0]
if pathuname not in (uname, "_" + uname):
- raiseOrPrint("The owner of %s directory %s is %s and does not match the expected owner: %s"
- % (description, path, pathuname, uname))
+ raiseOrPrint(
+ "The owner of %s directory %s is %s "
+ "and does not match the expected owner: %s"
+ % (description, path, pathuname, uname)
+ )
except KeyError:
- raiseOrPrint("The owner of %s directory %s is unknown (%s) and does not match the expected owner: %s"
- % (description, path, pathstat[stat.ST_UID], uname))
+ raiseOrPrint(
+ "The owner of %s directory %s is unknown (%s) "
+ "and does not match the expected owner: %s"
+ % (description, path, pathstat[stat.ST_UID], uname)
+ )
if gname:
import grp
try:
pathgname = grp.getgrgid(pathstat[stat.ST_GID])[0]
if pathgname != gname:
- raiseOrPrint("The group of %s directory %s is %s and does not match the expected group: %s"
- % (description, path, pathgname, gname))
+ raiseOrPrint(
+ "The group of %s directory %s is %s "
+ "and does not match the expected group: %s"
+ % (description, path, pathgname, gname)
+ )
except KeyError:
- raiseOrPrint("The group of %s directory %s is unknown (%s) and does not match the expected group: %s"
- % (description, path, pathstat[stat.ST_GID], gname))
+ raiseOrPrint(
+ "The group of %s directory %s is unknown (%s) "
+ "and does not match the expected group: %s"
+ % (description, path, pathstat[stat.ST_GID], gname)
+ )
from OpenSSL import SSL
from twisted.internet.ssl import DefaultOpenSSLContextFactory
+def _getSSLPassphrase(*args):
+ sslPrivKey = open(config.SSLPrivateKey)
+
+ type = None
+ for line in sslPrivKey.readlines():
+ if "-----BEGIN RSA PRIVATE KEY-----" in line:
+ type = "RSA"
+ break
+ elif "-----BEGIN DSA PRIVATE KEY-----" in line:
+ type = "DSA"
+ break
+
+ sslPrivKey.close()
+
+ if type is None:
+ logging.err("Could not get private key type for %s"
+ % (config.SSLPrivateKey,))
+ return False
+
+ import commands
+ return commands.getoutput("%s %s:%s %s" % (
+ config.SSLPassPhraseDialog,
+ config.ServerHostName,
+ config.SSLPort,
+ type
+ ))
+
+
class ChainingOpenSSLContextFactory(DefaultOpenSSLContextFactory):
- def __init__(self, privateKeyFileName, certificateFileName,
- sslmethod=SSL.SSLv23_METHOD, certificateChainFile=None):
+ def __init__(
+ self, privateKeyFileName, certificateFileName,
+ sslmethod=SSL.SSLv23_METHOD, certificateChainFile=None,
+ passwdCallback=None
+ ):
self.certificateChainFile = certificateChainFile
+ self.passwdCallback = passwdCallback
- DefaultOpenSSLContextFactory.__init__(self,
- privateKeyFileName,
- certificateFileName,
- sslmethod=sslmethod)
+ DefaultOpenSSLContextFactory.__init__(
+ self,
+ privateKeyFileName,
+ certificateFileName,
+ sslmethod=sslmethod
+ )
def cacheContext(self):
- DefaultOpenSSLContextFactory.cacheContext(self)
+ # Unfortunate code duplication.
+ ctx = SSL.Context(self.sslmethod)
- if self.certificateChainFile != '':
- self._context.use_certificate_chain_file(self.certificateChainFile)
+ if self.passwdCallback is not None:
+ ctx.set_passwd_cb(self.passwdCallback)
+ ctx.use_certificate_file(self.certificateFileName)
+ ctx.use_privatekey_file(self.privateKeyFileName)
+ if self.certificateChainFile != "":
+ ctx.use_certificate_chain_file(self.certificateChainFile)
+
+ self._context = ctx
+
+
class CalDAVServiceMaker(object):
implements(IPlugin, service.IServiceMaker)
@@ -346,7 +451,8 @@
def makeService_Slave(self, options):
- # Change log level to at least "info" as its useful to have that during startup
+ # Change log level to at least "info" as its useful to have
+ # that during startup
old_logging = logging.currentLogLevel
if logging.currentLogLevel < logging.logtypes["info"]:
logging.currentLogLevel = logging.logtypes["info"]
@@ -356,12 +462,12 @@
#
directories = []
- directoryClass = namedClass(config.DirectoryService['type'])
+ directoryClass = namedClass(config.DirectoryService["type"])
logging.info("Configuring directory service of type: %s"
- % (config.DirectoryService['type'],), system="startup")
+ % (config.DirectoryService['type'],), system="startup")
- baseDirectory = directoryClass(**config.DirectoryService['params'])
+ baseDirectory = directoryClass(**config.DirectoryService["params"])
directories.append(baseDirectory)
@@ -369,7 +475,7 @@
if config.SudoersFile and os.path.exists(config.SudoersFile):
logging.info("Configuring SudoDirectoryService with file: %s"
- % (config.SudoersFile,), system="startup")
+ % (config.SudoersFile,), system="startup")
sudoDirectory = SudoDirectoryService(config.SudoersFile)
sudoDirectory.realmName = baseDirectory.realmName
@@ -378,7 +484,7 @@
directories.insert(0, sudoDirectory)
else:
logging.info("Not using SudoDirectoryService; file doesn't exist: %s"
- % (config.SudoersFile,), system="startup")
+ % (config.SudoersFile,), system="startup")
directory = AggregateDirectoryService(directories)
@@ -390,25 +496,27 @@
# Setup Resource hierarchy
#
- logging.info("Setting up document root at: %s" % (config.DocumentRoot,), system="startup")
+ logging.info("Setting up document root at: %s"
+ % (config.DocumentRoot,), system="startup")
- logging.info("Setting up principal collection: %r" % (self.principalResourceClass,), system="startup")
+ logging.info("Setting up principal collection: %r"
+ % (self.principalResourceClass,), system="startup")
principalCollection = self.principalResourceClass(
- os.path.join(config.DocumentRoot, 'principals'),
- '/principals/',
- directory
+ os.path.join(config.DocumentRoot, "principals"),
+ "/principals/", directory
)
- logging.info("Setting up calendar collection: %r" % (self.calendarResourceClass,), system="startup")
+ logging.info("Setting up calendar collection: %r"
+ % (self.calendarResourceClass,), system="startup")
calendarCollection = self.calendarResourceClass(
- os.path.join(config.DocumentRoot, 'calendars'),
- directory,
- '/calendars/'
+ os.path.join(config.DocumentRoot, "calendars"),
+ directory, "/calendars/"
)
- logging.info("Setting up root resource: %r" % (self.rootResourceClass,), system="startup")
+ logging.info("Setting up root resource: %r"
+ % (self.rootResourceClass,), system="startup")
root = self.rootResourceClass(
config.DocumentRoot,
@@ -420,7 +528,8 @@
# Configure default ACLs on the root resource
- logging.info("Setting up default ACEs on root resource", system="startup")
+ logging.info("Setting up default ACEs on root resource",
+ system="startup")
rootACEs = [
davxml.ACE(
@@ -432,7 +541,8 @@
logging.info("Setting up AdminPrincipals", system="startup")
for principal in config.AdminPrincipals:
- logging.info("Added %s as admin principal" % (principal,), system="startup")
+ logging.info("Added %s as admin principal"
+ % (principal,), system="startup")
rootACEs.append(
davxml.ACE(
@@ -465,29 +575,38 @@
realm = directory.realmName or ""
- logging.info("Configuring authentication for realm: %s" % (realm,), system="startup")
+ logging.info("Configuring authentication for realm: %s"
+ % (realm,), system="startup")
for scheme, schemeConfig in config.Authentication.iteritems():
scheme = scheme.lower()
credFactory = None
- if schemeConfig['Enabled']:
- logging.info("Setting up scheme: %s" % (scheme,), system="startup")
+ if schemeConfig["Enabled"]:
+ logging.info("Setting up scheme: %s"
+ % (scheme,), system="startup")
- if scheme == 'kerberos':
+ if scheme == "kerberos":
if not NegotiateCredentialFactory:
- logging.info("Kerberos support not available", system="startup")
+ logging.info("Kerberos support not available",
+ system="startup")
continue
try:
- principal = schemeConfig['ServicePrincipal']
+ principal = schemeConfig["ServicePrincipal"]
if not principal:
- credFactory = NegotiateCredentialFactory(type="http", hostname=config.ServerHostName)
+ credFactory = NegotiateCredentialFactory(
+ type="http",
+ hostname=config.ServerHostName
+ )
else:
- credFactory = NegotiateCredentialFactory(principal=principal)
+ credFactory = NegotiateCredentialFactory(
+ principal=principal
+ )
except ValueError:
- logging.info("Could not start Kerberos", system="startup")
+ logging.info("Could not start Kerberos",
+ system="startup")
continue
elif scheme == 'digest':
@@ -502,7 +621,8 @@
credFactory = BasicCredentialFactory(realm)
else:
- logging.err("Unknown scheme: %s" % (scheme,), system="startup")
+ logging.err("Unknown scheme: %s"
+ % (scheme,), system="startup")
if credFactory:
credentialFactories.append(credFactory)
@@ -516,7 +636,10 @@
(auth.IPrincipal,)
)
- logWrapper = logging.DirectoryLogWrapperResource(authWrapper, directory)
+ logWrapper = logging.DirectoryLogWrapperResource(
+ authWrapper,
+ directory
+ )
#
# Configure the service
@@ -524,25 +647,32 @@
logging.info("Setting up service", system="startup")
- if config.ProcessType == 'Slave':
- if config.MultiProcess['ProcessCount'] > 1 and config.MultiProcess['LoadBalancer']['Enabled']:
+ if config.ProcessType == "Slave":
+ if (
+ config.MultiProcess["ProcessCount"] > 1 and
+ config.MultiProcess["LoadBalancer"]["Enabled"]
+ ):
realRoot = pdmonster.PDClientAddressWrapper(
logWrapper,
- config.PythonDirector['ControlSocket'],
+ config.PythonDirector["ControlSocket"],
directory
)
else:
realRoot = logWrapper
- logObserver = logging.AMPCommonAccessLoggingObserver(config.ControlSocket)
+ logObserver = logging.AMPCommonAccessLoggingObserver(
+ config.ControlSocket
+ )
- elif config.ProcessType == 'Single':
+ elif config.ProcessType == "Single":
realRoot = logWrapper
- logObserver = logging.RotatingFileAccessLoggingObserver(config.AccessLogFile)
+ logObserver = logging.RotatingFileAccessLoggingObserver(
+ config.AccessLogFile
+ )
- logging.info("Configuring log observer: %s" % (
- logObserver,), system="startup")
+ logging.info("Configuring log observer: %s"
+ % (logObserver,), system="startup")
service = CalDAVService(logObserver)
@@ -556,27 +686,45 @@
for bindAddress in config.BindAddresses:
if config.BindHTTPPorts:
if config.HTTPPort == 0:
- raise UsageError("HTTPPort required if BindHTTPPorts is not empty")
+ raise UsageError(
+ "HTTPPort required if BindHTTPPorts is not empty"
+ )
elif config.HTTPPort != 0:
config.BindHTTPPorts = [config.HTTPPort]
if config.BindSSLPorts:
if config.SSLPort == 0:
- raise UsageError("SSLPort required if BindSSLPorts is not empty")
+ raise UsageError(
+ "SSLPort required if BindSSLPorts is not empty"
+ )
elif config.SSLPort != 0:
config.BindSSLPorts = [config.SSLPort]
for port in config.BindHTTPPorts:
- logging.info("Adding server at %s:%s" % (bindAddress, port), system="startup")
+ logging.info("Adding server at %s:%s"
+ % (bindAddress, port), system="startup")
- httpService = internet.TCPServer(int(port), channel, interface=bindAddress)
+ httpService = internet.TCPServer(
+ int(port), channel,
+ interface=bindAddress
+ )
httpService.setServiceParent(service)
for port in config.BindSSLPorts:
- logging.info("Adding SSL server at %s:%s" % (bindAddress, port), system="startup")
+ logging.info("Adding SSL server at %s:%s"
+ % (bindAddress, port), system="startup")
- contextFactory = ChainingOpenSSLContextFactory(config.SSLPrivateKey, config.SSLCertificate, certificateChainFile=config.SSLAuthorityChain)
- httpsService = internet.SSLServer(int(port), channel, contextFactory, interface=bindAddress)
+ contextFactory = ChainingOpenSSLContextFactory(
+ config.SSLPrivateKey,
+ config.SSLCertificate,
+ certificateChainFile=config.SSLAuthorityChain,
+ passwdCallback=_getSSLPassphrase
+ )
+
+ httpsService = internet.SSLServer(
+ int(port), channel,
+ contextFactory, interface=bindAddress
+ )
httpsService.setServiceParent(service)
# Change log level back to what it was before
@@ -594,34 +742,39 @@
serviceMethod = getattr(self, "makeService_%s" % (serverType,), None)
if not serviceMethod:
- raise UsageError("Unknown server type %s. Please choose: Master, Slave or Combined"
- % (serverType,))
+ raise UsageError(
+ "Unknown server type %s. "
+ "Please choose: Master, Slave or Combined"
+ % (serverType,)
+ )
else:
service = serviceMethod(options)
+ #
# Temporary hack to work around SIGHUP problem
- # If there is a stopped process in the same session as the calendar server
- # and the calendar server is the group leader then when twistd forks to drop
- # privelages a SIGHUP may be sent by the kernel. This SIGHUP should be ignored.
- # Note that this handler is not unset, so any further SIGHUPs are also ignored.
+ # If there is a stopped process in the same session as the
+ # calendar server and the calendar server is the group
+ # leader then when twistd forks to drop privelages a
+ # SIGHUP may be sent by the kernel. This SIGHUP should be
+ # ignored.
+ # Note that this handler is not unset, so any further
+ # SIGHUPs are also ignored.
+ #
+
+ def location(frame):
+ if frame is None:
+ return "Unknown"
+ else:
+ return "%s: %s" % (frame.f_code.co_name, frame.f_lineno)
+
import signal
def sighup_handler(num, frame):
- if frame is None:
- location = "Unknown"
- else:
- location = str(frame.f_code.co_name) + ": " + str(frame.f_lineno)
- log.msg("SIGHUP recieved at " + location)
+ log.msg("SIGHUP recieved at %s" % (location(frame),))
signal.signal(signal.SIGHUP, sighup_handler)
def sigusr1_handler(num, frame):
- if frame is None:
- location = "Unknown"
- else:
- location = str(frame.f_code.co_name) + ": " + str(frame.f_lineno)
- log.msg("SIGUSR1 recieved at " + location)
+ log.msg("SIGUSR1 recieved at %s" % (location(frame),))
logging.toggle()
-
signal.signal(signal.SIGUSR1, sigusr1_handler)
return service
-
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080218/b53d5bea/attachment-0001.html
More information about the calendarserver-changes
mailing list