/RemoteControlServer/user.py

https://github.com/manuelnaranjo/remotecontrolserver · Python · 131 lines · 104 code · 9 blank · 18 comment · 1 complexity · c135fa3179ba3a9d6746e9275799f95b MD5 · raw file

  1. # -*- coding: utf-8 -*-
  2. # Copyright (c) 2010 Naranjo Manuel Francisco manuel@aircable.net
  3. # Copyright (c) 2009 Twisted Matrix Laboratories.
  4. # See LICENSE for details.
  5. from twisted.conch import avatar
  6. from twisted.conch.ssh import session, forwarding
  7. from twisted.conch.ssh.forwarding import openConnectForwardingClient
  8. from twisted.internet import reactor
  9. from twisted.internet.task import LoopingCall
  10. from twisted.conch.ssh.transport import DISCONNECT_RESERVED
  11. from time import time
  12. import struct
  13. from checker import PublicKeyCredentialsChecker
  14. from conf import config
  15. import database
  16. from twisted.python import log
  17. import os
  18. MINUTES=60
  19. if os.environ.has_key("DEBUG"):
  20. MINUTES=1
  21. # how many seconds make up a minute, defined as variable for debugging purposes
  22. def LoggedMonitor():
  23. print "Logged User Monitor: %s users" % len(ForwardUser.loggedin)
  24. def AnnonTimeout(user=None, loop=None):
  25. loop.stop()
  26. print "AnnonTimeout for %s" % user
  27. user.conn.transport.sendDisconnect(DISCONNECT_RESERVED,
  28. "Annonymous login expired")
  29. del ForwardUser.loggedin[user]
  30. class ForwardUser(avatar.ConchUser):
  31. """
  32. User that's has the needed methods to allow tcp forwarding
  33. """
  34. loggedin = dict()
  35. def __init__(self, username):
  36. avatar.ConchUser.__init__(self)
  37. self.username = username
  38. self.listeners={}
  39. self.pubkey = PublicKeyCredentialsChecker.instance.getKey(username)
  40. self.isannon = PublicKeyCredentialsChecker.instance.isAnnon(username)
  41. self.channelLookup.update({
  42. 'session':session.SSHSession,
  43. 'direct-tpcip': openConnectForwardingClient
  44. })
  45. if self.isannon:
  46. if config["ANNONYMOUS_TIMEOUT"] > 0:
  47. repeater=LoopingCall(AnnonTimeout, user=self)
  48. repeater.kw['loop']=repeater
  49. repeater.start(config["ANNONYMOUS_TIMEOUT"]*MINUTES, now=False)
  50. if not database.getUser(key=self.pubkey):
  51. database.createUser(key=self.pubkey,
  52. username=self.username,
  53. enabled=not self.isannon)
  54. # log user logged in
  55. database.updateUserLastLogin(key=self.pubkey)
  56. ForwardUser.loggedin[self]=time()
  57. def global_tcpip_forward(self, data):
  58. local, remote = forwarding.unpackOpen_direct_tcpip(data)
  59. hostToBind, portToBind = local
  60. log.msg("forward requested %s:%s" %( hostToBind, portToBind))
  61. log.msg(remote)
  62. try:
  63. listener = reactor.listenTCP(
  64. portToBind,
  65. forwarding.SSHListenForwardingFactory(
  66. self.conn,
  67. (hostToBind, portToBind),
  68. forwarding.SSHListenServerForwardingChannel),
  69. interface = hostToBind)
  70. listener.remote_host = remote[0]
  71. listener.remote_port = remote[1]
  72. except:
  73. return 0
  74. else:
  75. generated=False
  76. if portToBind == 0:
  77. portToBind = listener.getHost()[2] # the port
  78. print "generating port number", portToBind
  79. generated=True
  80. self.listeners[(hostToBind, portToBind)] = listener
  81. if generated:
  82. return 1, struct.pack('>L', portToBind)
  83. else:
  84. return 1
  85. def global_cancel_tcpip_forward(self, data):
  86. hostToBind, portToBind = forwarding.unpackGlobal_tcpip_forward(data)
  87. print "forward cancel requested", portToBind
  88. listener = self.listeners.get((hostToBind, portToBind), None)
  89. if not listener:
  90. return 0
  91. del self.listeners[(hostToBind, portToBind)]
  92. listener.stopListening()
  93. return 1
  94. def annon_disconnect(self):
  95. del ForwardUser.loggedin[self]
  96. self.conn.transport.sendDisconnect(DISCONNECT_RESERVED,
  97. "Annonymous login expired")
  98. self.logOut()
  99. def logOut(self):
  100. self.updateAccumulatedTime()
  101. def updateAccumulatedTime(self):
  102. database.updateUserAccumulatedTime(self.pubkey)
  103. def __str__(self):
  104. return "%s, %s" % ( self.username, self.isannon)
  105. repeater=LoopingCall(LoggedMonitor)
  106. repeater.start(10, now=False)