Skip to content

Commit

Permalink
add support for logging into utmp/wtmp. closes issue643.
Browse files Browse the repository at this point in the history
requires an external module, see INSTALL for location.


git-svn-id: svn://svn.twistedmatrix.com/svn/Twisted/trunk@11084 bbbe8e31-12d6-0310-92fd-ac37d47ddeeb
  • Loading branch information
z3p committed Jul 18, 2004
1 parent 4b0fb20 commit 33bb8c3
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2004-7-18 Paul Swartz <z3p@twistedmatrix.com>

* twisted/conch/unix.py: if the utmp module is available, record
user logins/logouts into utmp/wtmp.

2004-06-25 Paul Swartz <z3p@twistedmatrix.com>
* twisted/conch/checkers.py: Use functionality of crypt module instead
of an external module.
Expand Down
2 changes: 2 additions & 0 deletions INSTALL
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Requirements
GMPy (optional - http://gmpy.sf.net)
PyShadow (optional -
http://www.twistedmatrix.com/users/z3p/files/pyshadow-0.2.tar.gz)
Python-UTMP (optional -
http://melkor.dnp.fmph.uniba.sk/~garabik/python-utmp/)

Installation

Expand Down
40 changes: 38 additions & 2 deletions twisted/conch/unix.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@
from error import ConchError
from interfaces import ISession, ISFTPServer, ISFTPFile

import struct, array, os, stat, time
import struct, array, os, stat, time, socket
import fcntl, tty
import pwd
import pty
import ttymodes
import os

try:
import utmp
except ImportError:
utmp = None

class UnixSSHRealm:
__implements__ = portal.IRealm

Expand Down Expand Up @@ -131,6 +136,33 @@ def __init__(self, avatar):
self.pty = None
self.ptyTuple = 0

def addUTMPEntry(self, loggedIn=1):
if not utmp:
return
ipAddress = self.avatar.conn.transport.transport.getPeer().host
packedIp = struct.unpack('L', socket.inet_aton(ipAddress))[0]
ttyName = self.ptyTuple[2][5:]
t = time.time()
t1 = int(t)
t2 = int((t-t1) * 1e6)
entry = utmp.UtmpEntry()
entry.ut_type = loggedIn and utmp.USER_PROCESS or utmp.DEAD_PROCESS
entry.ut_pid = self.pty.pid
entry.ut_line = ttyName
entry.ut_id = ttyName[-4:]
entry.ut_tv = (t1,t2)
if loggedIn:
entry.ut_user = self.avatar.username
entry.ut_host = socket.gethostbyaddr(ipAddress)[0]
entry.ut_addr_v6 = (packedIp, 0, 0, 0)
a = utmp.UtmpRecord(utmp.UTMP_FILE)
a.pututline(entry)
a.endutent()
b = utmp.UtmpRecord(utmp.WTMP_FILE)
b.pututline(entry)
b.endutent()


def getPty(self, term, windowSize, modes):
self.environ['TERM'] = term
self.winSize = windowSize
Expand All @@ -151,13 +183,15 @@ def openShell(self, proto):
self.environ['USER'] = self.avatar.username
self.environ['HOME'] = homeDir
self.environ['SHELL'] = shell
shellExec = os.path.basename(shell)
peer = self.avatar.conn.transport.transport.getPeer()
host = self.avatar.conn.transport.transport.getHost()
self.environ['SSH_CLIENT'] = '%s %s %s' % (peer.host, peer.port, host.port)
self.getPtyOwnership()
self.pty = reactor.spawnProcess(proto, \
shell, ['-', '-i'], self.environ, homeDir, uid, gid,
shell, ['-%s' % shellExec], self.environ, homeDir, uid, gid,
usePTY = self.ptyTuple)
self.addUTMPEntry()
fcntl.ioctl(self.pty.fileno(), tty.TIOCSWINSZ,
struct.pack('4H', *self.winSize))
if self.modes:
Expand All @@ -181,6 +215,7 @@ def execCommand(self, proto, cmd):
shell, command, self.environ, homeDir,
uid, gid, usePTY = self.ptyTuple or 1)
if self.ptyTuple:
self.addUTMPEntry()
if self.modes:
self.setModes()
else:
Expand Down Expand Up @@ -237,6 +272,7 @@ def closed(self):
except OSError:
pass
self.pty.loseConnection()
self.addUTMPEntry(0)
log.msg('shell closed')

def windowChanged(self, winSize):
Expand Down

0 comments on commit 33bb8c3

Please sign in to comment.