forked from twisted/twisted
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinetdtap.py
122 lines (95 loc) · 3.79 KB
/
inetdtap.py
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
# -*- test-case-name: twisted.runner.test.test_inetdtap -*-
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Twisted inetd TAP support
The purpose of inetdtap is to provide an inetd-like server, to allow Twisted to
invoke other programs to handle incoming sockets.
This is a useful thing as a "networking swiss army knife" tool, like netcat.
"""
import pwd, grp, socket
from twisted.runner import inetd, inetdconf
from twisted.python import log, usage
from twisted.python.deprecate import deprecatedModuleAttribute
from incremental import Version
from twisted.internet.protocol import ServerFactory
from twisted.application import internet, service as appservice
# Protocol map
protocolDict = {'tcp': socket.IPPROTO_TCP, 'udp': socket.IPPROTO_UDP}
class Options(usage.Options):
"""
To use it, create a file named `sample-inetd.conf` with:
8123 stream tcp wait some_user /bin/cat -
You can then run it as in the following example and port 8123 became an
echo server.
twistd -n inetd -f sample-inetd.conf
"""
optParameters = [
['rpc', 'r', '/etc/rpc', 'DEPRECATED. 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):
"""
DEPRECATED.
"""
deprecatedModuleAttribute(
Version("Twisted", 16, 2, 0),
"The RPC server is no longer maintained.",
__name__, "RPCServer")
def makeService(config):
s = appservice.MultiService()
conf = inetdconf.InetdConf()
with open(config['file']) as f:
conf.parseFile(f)
for service in conf.services:
protocol = service.protocol
if service.protocol.startswith('rpc/'):
log.msg('Skipping rpc service due to lack of rpc support')
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 service.name not in inetd.internalProtocols:
log.msg('Unknown internal service: ' + service.name)
continue
factory = ServerFactory()
factory.protocol = inetd.internalProtocols[service.name]
else:
factory = inetd.InetdFactory(service)
if protocol == 'tcp':
internet.TCPServer(service.port, factory).setServiceParent(s)
elif protocol == 'udp':
raise RuntimeError("not supporting UDP")
return s