aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/Twisted/py3/twisted/protocols/ident.py
diff options
context:
space:
mode:
authorshmel1k <shmel1k@ydb.tech>2023-11-26 18:16:14 +0300
committershmel1k <shmel1k@ydb.tech>2023-11-26 18:43:30 +0300
commitb8cf9e88f4c5c64d9406af533d8948deb050d695 (patch)
tree218eb61fb3c3b96ec08b4d8cdfef383104a87d63 /contrib/python/Twisted/py3/twisted/protocols/ident.py
parent523f645a83a0ec97a0332dbc3863bb354c92a328 (diff)
downloadydb-b8cf9e88f4c5c64d9406af533d8948deb050d695.tar.gz
add kikimr_configure
Diffstat (limited to 'contrib/python/Twisted/py3/twisted/protocols/ident.py')
-rw-r--r--contrib/python/Twisted/py3/twisted/protocols/ident.py253
1 files changed, 253 insertions, 0 deletions
diff --git a/contrib/python/Twisted/py3/twisted/protocols/ident.py b/contrib/python/Twisted/py3/twisted/protocols/ident.py
new file mode 100644
index 0000000000..4401369119
--- /dev/null
+++ b/contrib/python/Twisted/py3/twisted/protocols/ident.py
@@ -0,0 +1,253 @@
+# -*- test-case-name: twisted.test.test_ident -*-
+# Copyright (c) Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+"""
+Ident protocol implementation.
+"""
+
+import struct
+
+from twisted.internet import defer
+from twisted.protocols import basic
+from twisted.python import failure, log
+
+_MIN_PORT = 1
+_MAX_PORT = 2**16 - 1
+
+
+class IdentError(Exception):
+ """
+ Can't determine connection owner; reason unknown.
+ """
+
+ identDescription = "UNKNOWN-ERROR"
+
+ def __str__(self) -> str:
+ return self.identDescription
+
+
+class NoUser(IdentError):
+ """
+ The connection specified by the port pair is not currently in use or
+ currently not owned by an identifiable entity.
+ """
+
+ identDescription = "NO-USER"
+
+
+class InvalidPort(IdentError):
+ """
+ Either the local or foreign port was improperly specified. This should
+ be returned if either or both of the port ids were out of range (TCP
+ port numbers are from 1-65535), negative integers, reals or in any
+ fashion not recognized as a non-negative integer.
+ """
+
+ identDescription = "INVALID-PORT"
+
+
+class HiddenUser(IdentError):
+ """
+ The server was able to identify the user of this port, but the
+ information was not returned at the request of the user.
+ """
+
+ identDescription = "HIDDEN-USER"
+
+
+class IdentServer(basic.LineOnlyReceiver):
+ """
+ The Identification Protocol (a.k.a., "ident", a.k.a., "the Ident
+ Protocol") provides a means to determine the identity of a user of a
+ particular TCP connection. Given a TCP port number pair, it returns a
+ character string which identifies the owner of that connection on the
+ server's system.
+
+ Server authors should subclass this class and override the lookup method.
+ The default implementation returns an UNKNOWN-ERROR response for every
+ query.
+ """
+
+ def lineReceived(self, line):
+ parts = line.split(",")
+ if len(parts) != 2:
+ self.invalidQuery()
+ else:
+ try:
+ portOnServer, portOnClient = map(int, parts)
+ except ValueError:
+ self.invalidQuery()
+ else:
+ if (
+ _MIN_PORT <= portOnServer <= _MAX_PORT
+ and _MIN_PORT <= portOnClient <= _MAX_PORT
+ ):
+ self.validQuery(portOnServer, portOnClient)
+ else:
+ self._ebLookup(
+ failure.Failure(InvalidPort()), portOnServer, portOnClient
+ )
+
+ def invalidQuery(self):
+ self.transport.loseConnection()
+
+ def validQuery(self, portOnServer, portOnClient):
+ """
+ Called when a valid query is received to look up and deliver the
+ response.
+
+ @param portOnServer: The server port from the query.
+ @param portOnClient: The client port from the query.
+ """
+ serverAddr = self.transport.getHost().host, portOnServer
+ clientAddr = self.transport.getPeer().host, portOnClient
+ defer.maybeDeferred(self.lookup, serverAddr, clientAddr).addCallback(
+ self._cbLookup, portOnServer, portOnClient
+ ).addErrback(self._ebLookup, portOnServer, portOnClient)
+
+ def _cbLookup(self, result, sport, cport):
+ (sysName, userId) = result
+ self.sendLine("%d, %d : USERID : %s : %s" % (sport, cport, sysName, userId))
+
+ def _ebLookup(self, failure, sport, cport):
+ if failure.check(IdentError):
+ self.sendLine("%d, %d : ERROR : %s" % (sport, cport, failure.value))
+ else:
+ log.err(failure)
+ self.sendLine(
+ "%d, %d : ERROR : %s" % (sport, cport, IdentError(failure.value))
+ )
+
+ def lookup(self, serverAddress, clientAddress):
+ """
+ Lookup user information about the specified address pair.
+
+ Return value should be a two-tuple of system name and username.
+ Acceptable values for the system name may be found online at::
+
+ U{http://www.iana.org/assignments/operating-system-names}
+
+ This method may also raise any IdentError subclass (or IdentError
+ itself) to indicate user information will not be provided for the
+ given query.
+
+ A Deferred may also be returned.
+
+ @param serverAddress: A two-tuple representing the server endpoint
+ of the address being queried. The first element is a string holding
+ a dotted-quad IP address. The second element is an integer
+ representing the port.
+
+ @param clientAddress: Like I{serverAddress}, but represents the
+ client endpoint of the address being queried.
+ """
+ raise IdentError()
+
+
+class ProcServerMixin:
+ """Implements lookup() to grab entries for responses from /proc/net/tcp"""
+
+ SYSTEM_NAME = "LINUX"
+
+ try:
+ from pwd import getpwuid # type:ignore[misc]
+
+ def getUsername(self, uid, getpwuid=getpwuid):
+ return getpwuid(uid)[0]
+
+ del getpwuid
+ except ImportError:
+
+ def getUsername(self, uid, getpwuid=None):
+ raise IdentError()
+
+ def entries(self):
+ with open("/proc/net/tcp") as f:
+ f.readline()
+ for L in f:
+ yield L.strip()
+
+ def dottedQuadFromHexString(self, hexstr):
+ return ".".join(
+ map(str, struct.unpack("4B", struct.pack("=L", int(hexstr, 16))))
+ )
+
+ def unpackAddress(self, packed):
+ addr, port = packed.split(":")
+ addr = self.dottedQuadFromHexString(addr)
+ port = int(port, 16)
+ return addr, port
+
+ def parseLine(self, line):
+ parts = line.strip().split()
+ localAddr, localPort = self.unpackAddress(parts[1])
+ remoteAddr, remotePort = self.unpackAddress(parts[2])
+ uid = int(parts[7])
+ return (localAddr, localPort), (remoteAddr, remotePort), uid
+
+ def lookup(self, serverAddress, clientAddress):
+ for ent in self.entries():
+ localAddr, remoteAddr, uid = self.parseLine(ent)
+ if remoteAddr == clientAddress and localAddr[1] == serverAddress[1]:
+ return (self.SYSTEM_NAME, self.getUsername(uid))
+
+ raise NoUser()
+
+
+class IdentClient(basic.LineOnlyReceiver):
+ errorTypes = (IdentError, NoUser, InvalidPort, HiddenUser)
+
+ def __init__(self):
+ self.queries = []
+
+ def lookup(self, portOnServer, portOnClient):
+ """
+ Lookup user information about the specified address pair.
+ """
+ self.queries.append((defer.Deferred(), portOnServer, portOnClient))
+ if len(self.queries) > 1:
+ return self.queries[-1][0]
+
+ self.sendLine("%d, %d" % (portOnServer, portOnClient))
+ return self.queries[-1][0]
+
+ def lineReceived(self, line):
+ if not self.queries:
+ log.msg(f"Unexpected server response: {line!r}")
+ else:
+ d, _, _ = self.queries.pop(0)
+ self.parseResponse(d, line)
+ if self.queries:
+ self.sendLine("%d, %d" % (self.queries[0][1], self.queries[0][2]))
+
+ def connectionLost(self, reason):
+ for q in self.queries:
+ q[0].errback(IdentError(reason))
+ self.queries = []
+
+ def parseResponse(self, deferred, line):
+ parts = line.split(":", 2)
+ if len(parts) != 3:
+ deferred.errback(IdentError(line))
+ else:
+ ports, type, addInfo = map(str.strip, parts)
+ if type == "ERROR":
+ for et in self.errorTypes:
+ if et.identDescription == addInfo:
+ deferred.errback(et(line))
+ return
+ deferred.errback(IdentError(line))
+ else:
+ deferred.callback((type, addInfo))
+
+
+__all__ = [
+ "IdentError",
+ "NoUser",
+ "InvalidPort",
+ "HiddenUser",
+ "IdentServer",
+ "IdentClient",
+ "ProcServerMixin",
+]