aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/runner/inetdtap.py
blob: 3e628779c9e189d4bc683aa3dab90dd9f3f5f5f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.

# 

"""
Twisted inetd TAP support

Maintainer: Andrew Bennetts

Future Plans: more configurability.
"""

import os, pwd, grp, socket

from twisted.runner import inetd, inetdconf
from twisted.python import log, usage
from twisted.internet.protocol import ServerFactory
from twisted.application import internet, service as appservice

try:
    import portmap
    rpcOk = 1
except ImportError:
    rpcOk = 0


# Protocol map
protocolDict = {'tcp': socket.IPPROTO_TCP, 'udp': socket.IPPROTO_UDP}


class Options(usage.Options):

    optParameters = [
        ['rpc', 'r', '/etc/rpc', 'RPC procedure table file'],
        ['file', 'f', '/etc/inetd.conf', 'Service configuration file']
    ]

    optFlags = [['nointernal', 'i', "Don't run internal services"]]

    compData = usage.Completions(
        optActions={"file": usage.CompleteFiles('*.conf')}
        )

class RPCServer(internet.TCPServer):

    def __init__(self, rpcVersions, rpcConf, proto, service):
        internet.TCPServer.__init__(0, ServerFactory())
        self.rpcConf = rpcConf
        self.proto = proto
        self.service = service

    def startService(self):
        internet.TCPServer.startService(self)
        import portmap
        portNo = self._port.getHost()[2]
        service = self.service
        for version in rpcVersions:
            portmap.set(self.rpcConf.services[name], version, self.proto,
                        portNo)
            inetd.forkPassingFD(service.program, service.programArgs,
                                os.environ, service.user, service.group, p)

def makeService(config):
    s = appservice.MultiService()
    conf = inetdconf.InetdConf()
    conf.parseFile(open(config['file']))

    rpcConf = inetdconf.RPCServicesConf()
    try:
        rpcConf.parseFile(open(config['rpc']))
    except:
        # We'll survive even if we can't read /etc/rpc
        log.deferr()
    
    for service in conf.services:
        rpc = service.protocol.startswith('rpc/')
        protocol = service.protocol

        if rpc and not rpcOk:
            log.msg('Skipping rpc service due to lack of rpc support')
            continue

        if rpc:
            # RPC has extra options, so extract that
            protocol = protocol[4:]     # trim 'rpc/'
            if not protocolDict.has_key(protocol):
                log.msg('Bad protocol: ' + protocol)
                continue
            
            try:
                name, rpcVersions = service.name.split('/')
            except ValueError:
                log.msg('Bad RPC service/version: ' + service.name)
                continue

            if not rpcConf.services.has_key(name):
                log.msg('Unknown RPC service: ' + repr(service.name))
                continue

            try:
                if '-' in rpcVersions:
                    start, end = map(int, rpcVersions.split('-'))
                    rpcVersions = range(start, end+1)
                else:
                    rpcVersions = [int(rpcVersions)]
            except ValueError:
                log.msg('Bad RPC versions: ' + str(rpcVersions))
                continue
            
        if (protocol, service.socketType) not in [('tcp', 'stream'),
                                                  ('udp', 'dgram')]:
            log.msg('Skipping unsupported type/protocol: %s/%s'
                    % (service.socketType, service.protocol))
            continue

        # Convert the username into a uid (if necessary)
        try:
            service.user = int(service.user)
        except ValueError:
            try:
                service.user = pwd.getpwnam(service.user)[2]
            except KeyError:
                log.msg('Unknown user: ' + service.user)
                continue

        # Convert the group name into a gid (if necessary)
        if service.group is None:
            # If no group was specified, use the user's primary group
            service.group = pwd.getpwuid(service.user)[3]
        else:
            try:
                service.group = int(service.group)
            except ValueError:
                try:
                    service.group = grp.getgrnam(service.group)[2]
                except KeyError:
                    log.msg('Unknown group: ' + service.group)
                    continue

        if service.program == 'internal':
            if config['nointernal']:
                continue

            # Internal services can use a standard ServerFactory
            if not inetd.internalProtocols.has_key(service.name):
                log.msg('Unknown internal service: ' + service.name)
                continue
            factory = ServerFactory()
            factory.protocol = inetd.internalProtocols[service.name]
        elif rpc:
            i = RPCServer(rpcVersions, rpcConf, proto, service)
            i.setServiceParent(s)
            continue
        else:
            # Non-internal non-rpc services use InetdFactory
            factory = inetd.InetdFactory(service)

        if protocol == 'tcp':
            internet.TCPServer(service.port, factory).setServiceParent(s)
        elif protocol == 'udp':
            raise RuntimeError("not supporting UDP")
    return s