| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
| 2 # See LICENSE for details. | |
| 3 | |
| 4 # | |
| 5 | |
| 6 """ | |
| 7 Twisted inetd TAP support | |
| 8 | |
| 9 Maintainer: U{Andrew Bennetts<mailto:spiv@twistedmatrix.com>} | |
| 10 | |
| 11 Future Plans: more configurability. | |
| 12 """ | |
| 13 | |
| 14 import os, pwd, grp, socket | |
| 15 | |
| 16 from twisted.runner import inetd, inetdconf | |
| 17 from twisted.python import log, usage | |
| 18 from twisted.internet.protocol import ServerFactory | |
| 19 from twisted.application import internet, service as appservice | |
| 20 | |
| 21 try: | |
| 22 import portmap | |
| 23 rpcOk = 1 | |
| 24 except ImportError: | |
| 25 rpcOk = 0 | |
| 26 | |
| 27 | |
| 28 # Protocol map | |
| 29 protocolDict = {'tcp': socket.IPPROTO_TCP, 'udp': socket.IPPROTO_UDP} | |
| 30 | |
| 31 | |
| 32 class Options(usage.Options): | |
| 33 | |
| 34 optParameters = [ | |
| 35 ['rpc', 'r', '/etc/rpc', 'RPC procedure table file'], | |
| 36 ['file', 'f', '/etc/inetd.conf', 'Service configuration file'] | |
| 37 ] | |
| 38 | |
| 39 optFlags = [['nointernal', 'i', "Don't run internal services"]] | |
| 40 zsh_actions = {"file" : "_files -g '*.conf'"} | |
| 41 | |
| 42 class RPCServer(internet.TCPServer): | |
| 43 | |
| 44 def __init__(self, rpcVersions, rpcConf, proto, service): | |
| 45 internet.TCPServer.__init__(0, ServerFactory()) | |
| 46 self.rpcConf = rpcConf | |
| 47 self.proto = proto | |
| 48 self.service = service | |
| 49 | |
| 50 def startService(self): | |
| 51 internet.TCPServer.startService(self) | |
| 52 import portmap | |
| 53 portNo = self._port.getHost()[2] | |
| 54 service = self.service | |
| 55 for version in rpcVersions: | |
| 56 portmap.set(self.rpcConf.services[name], version, self.proto, | |
| 57 portNo) | |
| 58 inetd.forkPassingFD(service.program, service.programArgs, | |
| 59 os.environ, service.user, service.group, p) | |
| 60 | |
| 61 def makeService(config): | |
| 62 s = appservice.MultiService() | |
| 63 conf = inetdconf.InetdConf() | |
| 64 conf.parseFile(open(config['file'])) | |
| 65 | |
| 66 rpcConf = inetdconf.RPCServicesConf() | |
| 67 try: | |
| 68 rpcConf.parseFile(open(config['rpc'])) | |
| 69 except: | |
| 70 # We'll survive even if we can't read /etc/rpc | |
| 71 log.deferr() | |
| 72 | |
| 73 for service in conf.services: | |
| 74 rpc = service.protocol.startswith('rpc/') | |
| 75 protocol = service.protocol | |
| 76 | |
| 77 if rpc and not rpcOk: | |
| 78 log.msg('Skipping rpc service due to lack of rpc support') | |
| 79 continue | |
| 80 | |
| 81 if rpc: | |
| 82 # RPC has extra options, so extract that | |
| 83 protocol = protocol[4:] # trim 'rpc/' | |
| 84 if not protocolDict.has_key(protocol): | |
| 85 log.msg('Bad protocol: ' + protocol) | |
| 86 continue | |
| 87 | |
| 88 try: | |
| 89 name, rpcVersions = service.name.split('/') | |
| 90 except ValueError: | |
| 91 log.msg('Bad RPC service/version: ' + service.name) | |
| 92 continue | |
| 93 | |
| 94 if not rpcConf.services.has_key(name): | |
| 95 log.msg('Unknown RPC service: ' + repr(service.name)) | |
| 96 continue | |
| 97 | |
| 98 try: | |
| 99 if '-' in rpcVersions: | |
| 100 start, end = map(int, rpcVersions.split('-')) | |
| 101 rpcVersions = range(start, end+1) | |
| 102 else: | |
| 103 rpcVersions = [int(rpcVersions)] | |
| 104 except ValueError: | |
| 105 log.msg('Bad RPC versions: ' + str(rpcVersions)) | |
| 106 continue | |
| 107 | |
| 108 if (protocol, service.socketType) not in [('tcp', 'stream'), | |
| 109 ('udp', 'dgram')]: | |
| 110 log.msg('Skipping unsupported type/protocol: %s/%s' | |
| 111 % (service.socketType, service.protocol)) | |
| 112 continue | |
| 113 | |
| 114 # Convert the username into a uid (if necessary) | |
| 115 try: | |
| 116 service.user = int(service.user) | |
| 117 except ValueError: | |
| 118 try: | |
| 119 service.user = pwd.getpwnam(service.user)[2] | |
| 120 except KeyError: | |
| 121 log.msg('Unknown user: ' + service.user) | |
| 122 continue | |
| 123 | |
| 124 # Convert the group name into a gid (if necessary) | |
| 125 if service.group is None: | |
| 126 # If no group was specified, use the user's primary group | |
| 127 service.group = pwd.getpwuid(service.user)[3] | |
| 128 else: | |
| 129 try: | |
| 130 service.group = int(service.group) | |
| 131 except ValueError: | |
| 132 try: | |
| 133 service.group = grp.getgrnam(service.group)[2] | |
| 134 except KeyError: | |
| 135 log.msg('Unknown group: ' + service.group) | |
| 136 continue | |
| 137 | |
| 138 if service.program == 'internal': | |
| 139 if config['nointernal']: | |
| 140 continue | |
| 141 | |
| 142 # Internal services can use a standard ServerFactory | |
| 143 if not inetd.internalProtocols.has_key(service.name): | |
| 144 log.msg('Unknown internal service: ' + service.name) | |
| 145 continue | |
| 146 factory = ServerFactory() | |
| 147 factory.protocol = inetd.internalProtocols[service.name] | |
| 148 elif rpc: | |
| 149 i = RPCServer(rpcVersions, rpcConf, proto, service) | |
| 150 i.setServiceParent(s) | |
| 151 continue | |
| 152 else: | |
| 153 # Non-internal non-rpc services use InetdFactory | |
| 154 factory = inetd.InetdFactory(service) | |
| 155 | |
| 156 if protocol == 'tcp': | |
| 157 internet.TCPServer(service.port, factory).setServiceParent(s) | |
| 158 elif protocol == 'udp': | |
| 159 raise RuntimeError("not supporting UDP") | |
| 160 return s | |
| OLD | NEW |