Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from time import sleep
- import subprocess,json, os
- from OpenSSL import SSL
- from twisted.internet import reactor,ssl
- from twisted.python import log
- from twisted.web import http
- from twisted.web.server import Site
- from twisted.web.static import File
- from twisted.web.static import Data
- from twisted.application import service, strports
- from twisted.web.guard import DigestCredentialFactory
- from twisted.web.resource import Resource
- from twisted.web.wsgi import WSGIResource
- from twisted.python.threadpool import ThreadPool
- from autobahn.resource import WebSocketResource, HTTPChannelHixie76Aware
- from autobahn.websocket import WebSocketServerFactory, \
- WebSocketServerProtocol, \
- listenWS
- from crypt import crypt
- factory = None
- class EchoServerProtocol(WebSocketServerProtocol):
- def onOpen(self):
- counter=0
- message = info()
- self.sendMessage(message)
- self.factory.register(self)
- def onConnect(self,request):
- if(self.transport not in self.factory.clients):
- raise http.HttpException(1008,"Nope")
- def connectionLost(self, reason):
- WebSocketServerProtocol.connectionLost(self, reason)
- self.factory.unregister(self)
- def onMessage(self,msg,binary):
- self.factory.broadcast(msg)
- class BroadcastServerFactory(WebSocketServerFactory):
- def __init__(self, url, debug = False, debugCodePaths = False):
- WebSocketServerFactory.__init__(self, url, debug = debug, debugCodePaths = debugCodePaths)
- self.clients = []
- reactor.callLater(10,self.tick)
- def tick(self):
- self.broadcast("hello world")
- reactor.callLater(10,self.tick)
- def register(self, client):
- if not client in self.clients:
- print "registered client " + client.peerstr
- self.clients.append(client)
- def unregister(self, client):
- if client in self.clients:
- print "unregistered client " + client.peerstr
- self.clients.remove(client)
- def broadcast(self,data):
- print 'sending data',data
- for c in self.clients:
- c.sendMessage(data)
- # Create and start a thread pool,
- wsgiThreadPool = ThreadPool()
- wsgiThreadPool.start()
- # ensuring that it will be stopped when the reactor shuts down
- reactor.addSystemEventTrigger('after', 'shutdown', wsgiThreadPool.stop)
- def application(environ, start_response):
- start_response('200 OK', [('Content-type','text/plain')])
- return ['Hello World!']
- __all__ = ['HtPasswdWrapper']
- class UnauthorizedResource(Resource):
- isLeaf = 1
- def __init__(self, realm, errorPage):
- Resource.__init__(self)
- self.realm = realm
- self.errorPage = errorPage
- def render(self, request):
- request.setResponseCode(http.UNAUTHORIZED)
- # FIXME: Does realm need to be quoted?
- request.setHeader('WWW-authenticate', 'basic realm="%s"' % self.realm)
- return self.errorPage.render(request)
- class HtPasswdWrapper(Resource):
- """Apache-style htpasswd protection for a resource.
- Requires a client to authenticate (using HTTP basic auth) to access a
- resource. If they fail to authenticate, or their username and password
- aren't accepted, they receive an error page.
- The username and password are checked against a htpasswd(1) file using
- crypt. The file is re-read for every request.
- TODO:
- - Integrate this into twisted.web.woven.guard / newcred?
- - Support MD5 password hashes in the htpasswd file, as well as crypt.
- @cvar unauthorizedPage: L{Resource} that will be used to render the error
- page given when a user is unauthorized.
- """
- unauthorizedPage = Data(
- '<html><body>Access Denied.</body></html>', 'text/html'
- )
- def __init__(self, resource, htpasswdFilename, realm):
- """Constructor.
- @param resource: resource to protect with authentication.
- @param htpasswdFilename: filename of an htpasswd file to authenticate
- with. Currently only crypt(3)-format passwords are supported.
- @param realm: HTTP auth realm.
- """
- Resource.__init__(self)
- self.resource = resource
- self.filename = htpasswdFilename
- self.realm = realm
- def getChildWithDefault(self, path, request):
- if self.authenticateUser(request):
- return self.resource.getChildWithDefault(path, request)
- else:
- return self.unauthorized()
- def render(self, request):
- global factory
- if self.authenticateUser(request):
- factory.client.append(self)
- return self.resource.render(request)
- else:
- return self.unauthorized().render(request)
- def authenticateUser(self, request):
- username, password = request.getUser(), request.getPassword()
- lines = [l.rstrip().split(':', 1) for l in file(self.filename).readlines()]
- lines = [l for l in lines if l[0] == username]
- if not lines:
- return 0
- hashedPassword = lines[0][1]
- return hashedPassword == crypt(password, hashedPassword[:2])
- def unauthorized(self):
- return UnauthorizedResource(self.realm, self.unauthorizedPage)
- if __name__ == '__main__':
- contextFactory = ssl.DefaultOpenSSLContextFactory('server.key',
- 'server.crt')
- print 'securing wss..'
- ServerFactory = BroadcastServerFactory
- factory = ServerFactory("wss://localhost:9000",debug = False)
- print 'opening ws port 9000'
- factory.protocol = EchoServerProtocol
- factory.setProtocolOptions(allowHixie76 = True)
- listenWS(factory,contextFactory)
- webdir = File("www/")
- web = Site(HtPasswdWrapper(webdir,'ht.passwd','websocket'))
- web.protocol = HTTPChannelHixie76Aware
- webdir.contentTypes['.crt'] = 'application/x-x509-ca-cert'
- resource = WSGIResource(reactor, reactor.getThreadPool(), application)
- reactor.listenSSL(443,web,contextFactory)
- print 'listening on port 443 for webserver'
- reactor.run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement