Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: third_party/twisted_8_1/twisted/conch/unix.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 from twisted.cred import portal
5 from twisted.python import components, log
6 from twisted.internet.error import ProcessExitedAlready
7 from zope import interface
8 from ssh import session, forwarding, filetransfer
9 from ssh.filetransfer import FXF_READ, FXF_WRITE, FXF_APPEND, FXF_CREAT, FXF_TRU NC, FXF_EXCL
10 from twisted.conch.ls import lsLine
11
12 from avatar import ConchUser
13 from error import ConchError
14 from interfaces import ISession, ISFTPServer, ISFTPFile
15
16 import struct, os, time, socket
17 import fcntl, tty
18 import pwd, grp
19 import pty
20 import ttymodes
21
22 try:
23 import utmp
24 except ImportError:
25 utmp = None
26
27 class UnixSSHRealm:
28 interface.implements(portal.IRealm)
29
30 def requestAvatar(self, username, mind, *interfaces):
31 user = UnixConchUser(username)
32 return interfaces[0], user, user.logout
33
34
35 class UnixConchUser(ConchUser):
36
37 def __init__(self, username):
38 ConchUser.__init__(self)
39 self.username = username
40 self.pwdData = pwd.getpwnam(self.username)
41 l = [self.pwdData[3]]
42 for groupname, password, gid, userlist in grp.getgrall():
43 if username in userlist:
44 l.append(gid)
45 self.otherGroups = l
46 self.listeners = {} # dict mapping (interface, port) -> listener
47 self.channelLookup.update(
48 {"session": session.SSHSession,
49 "direct-tcpip": forwarding.openConnectForwardingClient})
50
51 self.subsystemLookup.update(
52 {"sftp": filetransfer.FileTransferServer})
53
54 def getUserGroupId(self):
55 return self.pwdData[2:4]
56
57 def getOtherGroups(self):
58 return self.otherGroups
59
60 def getHomeDir(self):
61 return self.pwdData[5]
62
63 def getShell(self):
64 return self.pwdData[6]
65
66 def global_tcpip_forward(self, data):
67 hostToBind, portToBind = forwarding.unpackGlobal_tcpip_forward(data)
68 from twisted.internet import reactor
69 try: listener = self._runAsUser(
70 reactor.listenTCP, portToBind,
71 forwarding.SSHListenForwardingFactory(self.conn,
72 (hostToBind, portToBind),
73 forwarding.SSHListenServerForwardingChannel),
74 interface = hostToBind)
75 except:
76 return 0
77 else:
78 self.listeners[(hostToBind, portToBind)] = listener
79 if portToBind == 0:
80 portToBind = listener.getHost()[2] # the port
81 return 1, struct.pack('>L', portToBind)
82 else:
83 return 1
84
85 def global_cancel_tcpip_forward(self, data):
86 hostToBind, portToBind = forwarding.unpackGlobal_tcpip_forward(data)
87 listener = self.listeners.get((hostToBind, portToBind), None)
88 if not listener:
89 return 0
90 del self.listeners[(hostToBind, portToBind)]
91 self._runAsUser(listener.stopListening)
92 return 1
93
94 def logout(self):
95 # remove all listeners
96 for listener in self.listeners.itervalues():
97 self._runAsUser(listener.stopListening)
98 log.msg('avatar %s logging out (%i)' % (self.username, len(self.listener s)))
99
100 def _runAsUser(self, f, *args, **kw):
101 euid = os.geteuid()
102 egid = os.getegid()
103 groups = os.getgroups()
104 uid, gid = self.getUserGroupId()
105 os.setegid(0)
106 os.seteuid(0)
107 os.setgroups(self.getOtherGroups())
108 os.setegid(gid)
109 os.seteuid(uid)
110 try:
111 f = iter(f)
112 except TypeError:
113 f = [(f, args, kw)]
114 try:
115 for i in f:
116 func = i[0]
117 args = len(i)>1 and i[1] or ()
118 kw = len(i)>2 and i[2] or {}
119 r = func(*args, **kw)
120 finally:
121 os.setegid(0)
122 os.seteuid(0)
123 os.setgroups(groups)
124 os.setegid(egid)
125 os.seteuid(euid)
126 return r
127
128 class SSHSessionForUnixConchUser:
129
130 interface.implements(ISession)
131
132 def __init__(self, avatar):
133 self.avatar = avatar
134 self. environ = {'PATH':'/bin:/usr/bin:/usr/local/bin'}
135 self.pty = None
136 self.ptyTuple = 0
137
138 def addUTMPEntry(self, loggedIn=1):
139 if not utmp:
140 return
141 ipAddress = self.avatar.conn.transport.transport.getPeer().host
142 packedIp ,= struct.unpack('L', socket.inet_aton(ipAddress))
143 ttyName = self.ptyTuple[2][5:]
144 t = time.time()
145 t1 = int(t)
146 t2 = int((t-t1) * 1e6)
147 entry = utmp.UtmpEntry()
148 entry.ut_type = loggedIn and utmp.USER_PROCESS or utmp.DEAD_PROCESS
149 entry.ut_pid = self.pty.pid
150 entry.ut_line = ttyName
151 entry.ut_id = ttyName[-4:]
152 entry.ut_tv = (t1,t2)
153 if loggedIn:
154 entry.ut_user = self.avatar.username
155 entry.ut_host = socket.gethostbyaddr(ipAddress)[0]
156 entry.ut_addr_v6 = (packedIp, 0, 0, 0)
157 a = utmp.UtmpRecord(utmp.UTMP_FILE)
158 a.pututline(entry)
159 a.endutent()
160 b = utmp.UtmpRecord(utmp.WTMP_FILE)
161 b.pututline(entry)
162 b.endutent()
163
164
165 def getPty(self, term, windowSize, modes):
166 self.environ['TERM'] = term
167 self.winSize = windowSize
168 self.modes = modes
169 master, slave = pty.openpty()
170 ttyname = os.ttyname(slave)
171 self.environ['SSH_TTY'] = ttyname
172 self.ptyTuple = (master, slave, ttyname)
173
174 def openShell(self, proto):
175 from twisted.internet import reactor
176 if not self.ptyTuple: # we didn't get a pty-req
177 log.msg('tried to get shell without pty, failing')
178 raise ConchError("no pty")
179 uid, gid = self.avatar.getUserGroupId()
180 homeDir = self.avatar.getHomeDir()
181 shell = self.avatar.getShell()
182 self.environ['USER'] = self.avatar.username
183 self.environ['HOME'] = homeDir
184 self.environ['SHELL'] = shell
185 shellExec = os.path.basename(shell)
186 peer = self.avatar.conn.transport.transport.getPeer()
187 host = self.avatar.conn.transport.transport.getHost()
188 self.environ['SSH_CLIENT'] = '%s %s %s' % (peer.host, peer.port, host.po rt)
189 self.getPtyOwnership()
190 self.pty = reactor.spawnProcess(proto, \
191 shell, ['-%s' % shellExec], self.environ, homeDir, uid, gid,
192 usePTY = self.ptyTuple)
193 self.addUTMPEntry()
194 fcntl.ioctl(self.pty.fileno(), tty.TIOCSWINSZ,
195 struct.pack('4H', *self.winSize))
196 if self.modes:
197 self.setModes()
198 self.oldWrite = proto.transport.write
199 proto.transport.write = self._writeHack
200 self.avatar.conn.transport.transport.setTcpNoDelay(1)
201
202 def execCommand(self, proto, cmd):
203 from twisted.internet import reactor
204 uid, gid = self.avatar.getUserGroupId()
205 homeDir = self.avatar.getHomeDir()
206 shell = self.avatar.getShell() or '/bin/sh'
207 command = (shell, '-c', cmd)
208 peer = self.avatar.conn.transport.transport.getPeer()
209 host = self.avatar.conn.transport.transport.getHost()
210 self.environ['SSH_CLIENT'] = '%s %s %s' % (peer.host, peer.port, host.po rt)
211 if self.ptyTuple:
212 self.getPtyOwnership()
213 self.pty = reactor.spawnProcess(proto, \
214 shell, command, self.environ, homeDir,
215 uid, gid, usePTY = self.ptyTuple or 0)
216 if self.ptyTuple:
217 self.addUTMPEntry()
218 if self.modes:
219 self.setModes()
220 # else:
221 # tty.setraw(self.pty.pipes[0].fileno(), tty.TCSANOW)
222 self.avatar.conn.transport.transport.setTcpNoDelay(1)
223
224 def getPtyOwnership(self):
225 ttyGid = os.stat(self.ptyTuple[2])[5]
226 uid, gid = self.avatar.getUserGroupId()
227 euid, egid = os.geteuid(), os.getegid()
228 os.setegid(0)
229 os.seteuid(0)
230 try:
231 os.chown(self.ptyTuple[2], uid, ttyGid)
232 finally:
233 os.setegid(egid)
234 os.seteuid(euid)
235
236 def setModes(self):
237 pty = self.pty
238 attr = tty.tcgetattr(pty.fileno())
239 for mode, modeValue in self.modes:
240 if not ttymodes.TTYMODES.has_key(mode): continue
241 ttyMode = ttymodes.TTYMODES[mode]
242 if len(ttyMode) == 2: # flag
243 flag, ttyAttr = ttyMode
244 if not hasattr(tty, ttyAttr): continue
245 ttyval = getattr(tty, ttyAttr)
246 if modeValue:
247 attr[flag] = attr[flag]|ttyval
248 else:
249 attr[flag] = attr[flag]&~ttyval
250 elif ttyMode == 'OSPEED':
251 attr[tty.OSPEED] = getattr(tty, 'B%s'%modeValue)
252 elif ttyMode == 'ISPEED':
253 attr[tty.ISPEED] = getattr(tty, 'B%s'%modeValue)
254 else:
255 if not hasattr(tty, ttyMode): continue
256 ttyval = getattr(tty, ttyMode)
257 attr[tty.CC][ttyval] = chr(modeValue)
258 tty.tcsetattr(pty.fileno(), tty.TCSANOW, attr)
259
260 def eofReceived(self):
261 if self.pty:
262 self.pty.closeStdin()
263
264 def closed(self):
265 if self.ptyTuple and os.path.exists(self.ptyTuple[2]):
266 ttyGID = os.stat(self.ptyTuple[2])[5]
267 os.chown(self.ptyTuple[2], 0, ttyGID)
268 if self.pty:
269 try:
270 self.pty.signalProcess('HUP')
271 except (OSError,ProcessExitedAlready):
272 pass
273 self.pty.loseConnection()
274 self.addUTMPEntry(0)
275 log.msg('shell closed')
276
277 def windowChanged(self, winSize):
278 self.winSize = winSize
279 fcntl.ioctl(self.pty.fileno(), tty.TIOCSWINSZ,
280 struct.pack('4H', *self.winSize))
281
282 def _writeHack(self, data):
283 """
284 Hack to send ignore messages when we aren't echoing.
285 """
286 if self.pty is not None:
287 attr = tty.tcgetattr(self.pty.fileno())[3]
288 if not attr & tty.ECHO and attr & tty.ICANON: # no echo
289 self.avatar.conn.transport.sendIgnore('\x00'*(8+len(data)))
290 self.oldWrite(data)
291
292
293 class SFTPServerForUnixConchUser:
294
295 interface.implements(ISFTPServer)
296
297 def __init__(self, avatar):
298 self.avatar = avatar
299
300
301 def _setAttrs(self, path, attrs):
302 """
303 NOTE: this function assumes it runs as the logged-in user:
304 i.e. under _runAsUser()
305 """
306 if attrs.has_key("uid") and attrs.has_key("gid"):
307 os.chown(path, attrs["uid"], attrs["gid"])
308 if attrs.has_key("permissions"):
309 os.chmod(path, attrs["permissions"])
310 if attrs.has_key("atime") and attrs.has_key("mtime"):
311 os.utime(path, (attrs["atime"], attrs["mtime"]))
312
313 def _getAttrs(self, s):
314 return {
315 "size" : s.st_size,
316 "uid" : s.st_uid,
317 "gid" : s.st_gid,
318 "permissions" : s.st_mode,
319 "atime" : int(s.st_atime),
320 "mtime" : int(s.st_mtime)
321 }
322
323 def _absPath(self, path):
324 home = self.avatar.getHomeDir()
325 return os.path.abspath(os.path.join(home, path))
326
327 def gotVersion(self, otherVersion, extData):
328 return {}
329
330 def openFile(self, filename, flags, attrs):
331 return UnixSFTPFile(self, self._absPath(filename), flags, attrs)
332
333 def removeFile(self, filename):
334 filename = self._absPath(filename)
335 return self.avatar._runAsUser(os.remove, filename)
336
337 def renameFile(self, oldpath, newpath):
338 oldpath = self._absPath(oldpath)
339 newpath = self._absPath(newpath)
340 return self.avatar._runAsUser(os.rename, oldpath, newpath)
341
342 def makeDirectory(self, path, attrs):
343 path = self._absPath(path)
344 return self.avatar._runAsUser([(os.mkdir, (path,)),
345 (self._setAttrs, (path, attrs))])
346
347 def removeDirectory(self, path):
348 path = self._absPath(path)
349 self.avatar._runAsUser(os.rmdir, path)
350
351 def openDirectory(self, path):
352 return UnixSFTPDirectory(self, self._absPath(path))
353
354 def getAttrs(self, path, followLinks):
355 path = self._absPath(path)
356 if followLinks:
357 s = self.avatar._runAsUser(os.stat, path)
358 else:
359 s = self.avatar._runAsUser(os.lstat, path)
360 return self._getAttrs(s)
361
362 def setAttrs(self, path, attrs):
363 path = self._absPath(path)
364 self.avatar._runAsUser(self._setAttrs, path, attrs)
365
366 def readLink(self, path):
367 path = self._absPath(path)
368 return self.avatar._runAsUser(os.readlink, path)
369
370 def makeLink(self, linkPath, targetPath):
371 linkPath = self._absPath(linkPath)
372 targetPath = self._absPath(targetPath)
373 return self.avatar._runAsUser(os.symlink, targetPath, linkPath)
374
375 def realPath(self, path):
376 return os.path.realpath(self._absPath(path))
377
378 def extendedRequest(self, extName, extData):
379 raise NotImplementedError
380
381 class UnixSFTPFile:
382
383 interface.implements(ISFTPFile)
384
385 def __init__(self, server, filename, flags, attrs):
386 self.server = server
387 openFlags = 0
388 if flags & FXF_READ == FXF_READ and flags & FXF_WRITE == 0:
389 openFlags = os.O_RDONLY
390 if flags & FXF_WRITE == FXF_WRITE and flags & FXF_READ == 0:
391 openFlags = os.O_WRONLY
392 if flags & FXF_WRITE == FXF_WRITE and flags & FXF_READ == FXF_READ:
393 openFlags = os.O_RDWR
394 if flags & FXF_APPEND == FXF_APPEND:
395 openFlags |= os.O_APPEND
396 if flags & FXF_CREAT == FXF_CREAT:
397 openFlags |= os.O_CREAT
398 if flags & FXF_TRUNC == FXF_TRUNC:
399 openFlags |= os.O_TRUNC
400 if flags & FXF_EXCL == FXF_EXCL:
401 openFlags |= os.O_EXCL
402 if attrs.has_key("permissions"):
403 mode = attrs["permissions"]
404 del attrs["permissions"]
405 else:
406 mode = 0777
407 fd = server.avatar._runAsUser(os.open, filename, openFlags, mode)
408 if attrs:
409 server.avatar._runAsUser(server._setAttrs, filename, attrs)
410 self.fd = fd
411
412 def close(self):
413 return self.server.avatar._runAsUser(os.close, self.fd)
414
415 def readChunk(self, offset, length):
416 return self.server.avatar._runAsUser([ (os.lseek, (self.fd, offset, 0)),
417 (os.read, (self.fd, length)) ])
418
419 def writeChunk(self, offset, data):
420 return self.server.avatar._runAsUser([(os.lseek, (self.fd, offset, 0)),
421 (os.write, (self.fd, data))])
422
423 def getAttrs(self):
424 s = self.server.avatar._runAsUser(os.fstat, self.fd)
425 return self.server._getAttrs(s)
426
427 def setAttrs(self, attrs):
428 raise NotImplementedError
429
430
431 class UnixSFTPDirectory:
432
433 def __init__(self, server, directory):
434 self.server = server
435 self.files = server.avatar._runAsUser(os.listdir, directory)
436 self.dir = directory
437
438 def __iter__(self):
439 return self
440
441 def next(self):
442 try:
443 f = self.files.pop(0)
444 except IndexError:
445 raise StopIteration
446 else:
447 s = self.server.avatar._runAsUser(os.lstat, os.path.join(self.dir, f ))
448 longname = lsLine(f, s)
449 attrs = self.server._getAttrs(s)
450 return (f, longname, attrs)
451
452 def close(self):
453 self.files = []
454
455
456 components.registerAdapter(SFTPServerForUnixConchUser, UnixConchUser, filetransf er.ISFTPServer)
457 components.registerAdapter(SSHSessionForUnixConchUser, UnixConchUser, session.IS ession)
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/conch/ui/tkvt100.py ('k') | third_party/twisted_8_1/twisted/copyright.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698