From 0b36a3fdb697f99fbff20693a1ed8147795680b3 Mon Sep 17 00:00:00 2001 From: li qun Date: Wed, 28 Feb 2018 11:11:18 +0800 Subject: [PATCH 1/5] Add function using path in URL as VNC server:port --- websockify/encode_url.py | 79 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 websockify/encode_url.py diff --git a/websockify/encode_url.py b/websockify/encode_url.py new file mode 100644 index 0000000..da78d2c --- /dev/null +++ b/websockify/encode_url.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +'''The program encode and decode the string with base64 and hash to validate the integrality. +''' +import sys +import hashlib +import base64 +# Please change the salt for your own project. +SALT = "Some salt for security. liqun@ncl.sg" +def encode(str): + ''' The func encode str, hash it and base64 it.''' + alg = hashlib.sha256() + alg.update(str) + alg.update(SALT) + hash = alg.hexdigest() + return base64.urlsafe_b64encode(hash+':'+str) +def decode(str): + ''' The func decode str, validate with hash and base64.decode it.''' + str1 = base64.urlsafe_b64decode(str) + pos = str1.find(':') + if pos == -1: + return '' + hash = str1[0:pos] + alg = hashlib.sha256() + alg.update(str1[pos+1:]) + alg.update(SALT) + hash1 = alg.hexdigest() + if hash != hash1: + print "Error: str hash different" + return '' + return str1[pos+1:] +def get_server_from_path(path, is_encoded): + '''The func decode host port from path parameter. + path looks like [/encode(n1.soc.cloud.ncl.sg:5901)] + ''' + try: + if is_encoded: + str = decode(path[1:]) + else: + str = path[1:] + if str == '': + return '', 0 + phost = '' + phost = str.split(':')[0] + pport = int(str.split(':')[1]) + except: + return phost, 0 + return phost, pport + +def test_basic(): + '''The func test some basic func.''' + assert get_server_from_path('/n1.soc.cloud.ncl.sg:5901', False) == ('n1.soc.cloud.ncl.sg', 5901) + + str = "n1.soc.cloud.ncl.sg:5901" + enc = encode(str) + dec = decode(enc) + assert str == dec + assert get_server_from_path('/'+enc, True) == ('n1.soc.cloud.ncl.sg', 5901) +def main(): + '''The func is the main func.''' + import sys + if (len(sys.argv) == 2) and (sys.argv[1] == "test"): + test_basic() + print "Pass all test" + exit() + elif (len(sys.argv) == 2): + print encode(sys.argv[1]) + elif (len(sys.argv) == 3) and (sys.argv[1] == "decode"): + print decode(sys.argv[2]) + elif (len(sys.argv) == 3) and (sys.argv[1] == "debase"): + str1 = base64.urlsafe_b64decode(sys.argv[2]) + print str1 + else: + print '''%s [content to encode] + decode [content to decode] + test''' % sys.argv[0] + +if __name__ == "__main__": + main() + From 6d4663de47c601f4aebf679ba5da8189cb84a70b Mon Sep 17 00:00:00 2001 From: li qun Date: Wed, 28 Feb 2018 14:28:07 +0800 Subject: [PATCH 2/5] Use encoded path in URL as vnc server:port Normally we only specify one vncserver address. Now we can generator URL with path=vncserver:port and user can use the link to connect vncserver:port. The path can be encoded with hash and creating date, then user can not change it and the link will be invalid after a few days. --- websockify/encode_url.py | 59 ++++++++++++++++++++++++------------ websockify/websocketproxy.py | 25 ++++++++++++++- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/websockify/encode_url.py b/websockify/encode_url.py index da78d2c..ce2546d 100644 --- a/websockify/encode_url.py +++ b/websockify/encode_url.py @@ -4,37 +4,46 @@ import sys import hashlib import base64 +import datetime # Please change the salt for your own project. SALT = "Some salt for security. liqun@ncl.sg" -def encode(str): +def qencode(str, create_date=datetime.date.today(), salt=SALT): ''' The func encode str, hash it and base64 it.''' alg = hashlib.sha256() + tstr = create_date.strftime("%Y%m%d") + alg.update(tstr) + alg.update(':') alg.update(str) - alg.update(SALT) + alg.update(salt) hash = alg.hexdigest() - return base64.urlsafe_b64encode(hash+':'+str) -def decode(str): - ''' The func decode str, validate with hash and base64.decode it.''' + return base64.urlsafe_b64encode(hash+tstr+':'+str) +def qdecode(str, valid_daynum=3, salt=SALT): + ''' The func decode str, validate with hash and base64.decode it. + If valid_daynum =0, only today is valid.''' str1 = base64.urlsafe_b64decode(str) pos = str1.find(':') if pos == -1: return '' - hash = str1[0:pos] + hash = str1[0:pos-8] + tstr = str1[pos-8:pos] + url_date = datetime.date(int(str1[pos-8:pos-4]), int(str1[pos-4:pos-2]), int(str1[pos-2:pos])) + today = datetime.date.today() + if (today - url_date) > datetime.timedelta(valid_daynum): + return '' alg = hashlib.sha256() - alg.update(str1[pos+1:]) - alg.update(SALT) + alg.update(str1[pos-8:]) + alg.update(salt) hash1 = alg.hexdigest() if hash != hash1: - print "Error: str hash different" return '' return str1[pos+1:] -def get_server_from_path(path, is_encoded): +def get_server_from_path(path, is_encoded, valid_daynum=3, salt=SALT): '''The func decode host port from path parameter. - path looks like [/encode(n1.soc.cloud.ncl.sg:5901)] + path looks like [/qencode(n1.soc.cloud.ncl.sg:5901)] ''' try: if is_encoded: - str = decode(path[1:]) + str = qdecode(path[1:], valid_daynum, salt) else: str = path[1:] if str == '': @@ -51,10 +60,19 @@ def test_basic(): assert get_server_from_path('/n1.soc.cloud.ncl.sg:5901', False) == ('n1.soc.cloud.ncl.sg', 5901) str = "n1.soc.cloud.ncl.sg:5901" - enc = encode(str) - dec = decode(enc) + enc = qencode(str) + print enc + print base64.urlsafe_b64decode(enc) + dec = qdecode(enc) assert str == dec assert get_server_from_path('/'+enc, True) == ('n1.soc.cloud.ncl.sg', 5901) + enc = qencode(str, datetime.date(2018, 2, 24)) + assert (get_server_from_path('/'+enc, True)) == ('', 0) + enc = qencode(str, datetime.date.today(), 'test salt') + dec = qdecode(enc, 3, 'test salt') + assert str == dec + dec = qdecode(enc, 3, 'test salt1') + assert dec == '' def main(): '''The func is the main func.''' import sys @@ -63,17 +81,20 @@ def main(): print "Pass all test" exit() elif (len(sys.argv) == 2): - print encode(sys.argv[1]) + print qencode(sys.argv[1]) elif (len(sys.argv) == 3) and (sys.argv[1] == "decode"): - print decode(sys.argv[2]) + print qdecode(sys.argv[2]) + elif (len(sys.argv) == 5) and (sys.argv[1] == "decode"): + print qdecode(sys.argv[2],sys.argv[3],sys.argv[4]) + elif (len(sys.argv) == 5) and (sys.argv[1] == "encode"): + print qencode(sys.argv[2],sys.argv[3],sys.argv[4]) elif (len(sys.argv) == 3) and (sys.argv[1] == "debase"): str1 = base64.urlsafe_b64decode(sys.argv[2]) print str1 else: - print '''%s [content to encode] - decode [content to decode] + print '''%s [content to encode] [valid day number:3] [salt to encrypt] + decode [content to decode] [valid day number:3] [salt to encrypt] test''' % sys.argv[0] if __name__ == "__main__": main() - diff --git a/websockify/websocketproxy.py b/websockify/websocketproxy.py index 6c17c10..7adcd1f 100644 --- a/websockify/websocketproxy.py +++ b/websockify/websocketproxy.py @@ -30,6 +30,15 @@ try: except ImportError: from cgi import parse_qs from urlparse import urlparse +# Switch to open function let URL path define path. +# &path=vncserver.domain.name:port +URL_PATH_DEF_VNCSERVER = True +# Whether is URL path encoded +URL_PATH_ENCODED = False +# URL valid day number after creating. +URL_VALID_DAYNUM = 3 +# Salt used to valide the hash of the URL. +URL_SALT = 'Some salt used to hash the URL for integrity validation. liqun@ncl.sg' class ProxyRequestHandler(websockifyserver.WebSockifyRequestHandler): @@ -100,6 +109,13 @@ Traffic Legend: msg = "connecting to command: '%s' (port %s)" % (" ".join(self.server.wrap_cmd), self.server.target_port) elif self.server.unix_target: msg = "connecting to unix socket: %s" % self.server.unix_target + elif URL_PATH_DEF_VNCSERVER: + import encode_url + (ptarget_host, ptarget_port) = encode_url.get_server_from_path(\ + self.path, URL_PATH_ENCODED, URL_VALID_DAYNUM, URL_SALT) + if ptarget_port == 0: + raise self.server.EClose('Cannot decode path.') + msg = "connecting to: %s:%s" % (ptarget_host, ptarget_port) else: msg = "connecting to: %s:%s" % ( self.server.target_host, self.server.target_port) @@ -108,7 +124,14 @@ Traffic Legend: msg += " (using SSL)" self.log_message(msg) - tsock = websockifyserver.WebSockifyServer.socket(self.server.target_host, + if URL_PATH_DEF_VNCSERVER: + tsock = websockifyserver.WebSockifyServer.socket(ptarget_host, + ptarget_port, + connect=True, + use_ssl=self.server.ssl_target, + unix_socket=self.server.unix_target) + else: + tsock = websockifyserver.WebSockifyServer.socket(self.server.target_host, self.server.target_port, connect=True, use_ssl=self.server.ssl_target, From 2de9b5a78a772a7ccceebfda5b54708cc6d5dea0 Mon Sep 17 00:00:00 2001 From: QunL Date: Tue, 6 Mar 2018 10:59:16 +0800 Subject: [PATCH 3/5] support dir in path; you can add usernmae in path. --- websockify/encode_url.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/websockify/encode_url.py b/websockify/encode_url.py index ce2546d..6871b3a 100644 --- a/websockify/encode_url.py +++ b/websockify/encode_url.py @@ -6,7 +6,7 @@ import hashlib import base64 import datetime # Please change the salt for your own project. -SALT = "Some salt for security. liqun@ncl.sg" +SALT = "Some salt for security. Please change it in your project. liqun@ncl.sg" def qencode(str, create_date=datetime.date.today(), salt=SALT): ''' The func encode str, hash it and base64 it.''' alg = hashlib.sha256() @@ -42,10 +42,13 @@ def get_server_from_path(path, is_encoded, valid_daynum=3, salt=SALT): path looks like [/qencode(n1.soc.cloud.ncl.sg:5901)] ''' try: + pos = path.rfind('/') + if pos == -1: + return '', 0 if is_encoded: - str = qdecode(path[1:], valid_daynum, salt) + str = qdecode(path[pos+1:], valid_daynum, salt) else: - str = path[1:] + str = path[pos+1:] if str == '': return '', 0 phost = '' @@ -73,6 +76,13 @@ def test_basic(): assert str == dec dec = qdecode(enc, 3, 'test salt1') assert dec == '' + str = "n1.soc.cloud.ncl.sg:5901:ntechni3" + enc = qencode(str) + print enc + print base64.urlsafe_b64decode(enc) + dec = qdecode(enc) + assert str == dec + assert get_server_from_path('/'+enc, True) == ('n1.soc.cloud.ncl.sg', 5901) def main(): '''The func is the main func.''' import sys From 0821efdae53a697d40c6303d496052566b9c2e5f Mon Sep 17 00:00:00 2001 From: QunL Date: Thu, 29 Mar 2018 10:48:10 +0800 Subject: [PATCH 4/5] add err msg; check group policy; bug fix. --- websockify/encode_url.py | 80 +++++++++---- websockify/group.py | 221 +++++++++++++++++++++++++++++++++++ websockify/websocketproxy.py | 8 +- 3 files changed, 286 insertions(+), 23 deletions(-) create mode 100644 websockify/group.py diff --git a/websockify/encode_url.py b/websockify/encode_url.py index 6871b3a..38e0f0b 100644 --- a/websockify/encode_url.py +++ b/websockify/encode_url.py @@ -5,7 +5,9 @@ import sys import hashlib import base64 import datetime +import group # Please change the salt for your own project. +#SALT = "Some salt for security. liqun@ncl.sg" SALT = "Some salt for security. Please change it in your project. liqun@ncl.sg" def qencode(str, create_date=datetime.date.today(), salt=SALT): ''' The func encode str, hash it and base64 it.''' @@ -20,42 +22,57 @@ def qencode(str, create_date=datetime.date.today(), salt=SALT): def qdecode(str, valid_daynum=3, salt=SALT): ''' The func decode str, validate with hash and base64.decode it. If valid_daynum =0, only today is valid.''' - str1 = base64.urlsafe_b64decode(str) + if str[-1] == '/': + str1 = base64.urlsafe_b64decode(str[0:-1]) + else: + str1 = base64.urlsafe_b64decode(str) pos = str1.find(':') if pos == -1: - return '' + return '','Err:not find :' hash = str1[0:pos-8] tstr = str1[pos-8:pos] url_date = datetime.date(int(str1[pos-8:pos-4]), int(str1[pos-4:pos-2]), int(str1[pos-2:pos])) today = datetime.date.today() if (today - url_date) > datetime.timedelta(valid_daynum): - return '' + return '', 'Err: Timeout' alg = hashlib.sha256() alg.update(str1[pos-8:]) alg.update(salt) hash1 = alg.hexdigest() if hash != hash1: - return '' - return str1[pos+1:] -def get_server_from_path(path, is_encoded, valid_daynum=3, salt=SALT): + return '', 'Err: Wrong hash' + return str1[pos+1:], '' +def get_server_from_path(path, is_encoded, valid_daynum=3, salt=SALT, gpolicy=group.gpolicy): '''The func decode host port from path parameter. path looks like [/qencode(n1.soc.cloud.ncl.sg:5901)] ''' + phost = '' + if path[-1] == '/': + path = path[0:-1] + try: pos = path.rfind('/') if pos == -1: return '', 0 if is_encoded: - str = qdecode(path[pos+1:], valid_daynum, salt) + (str,err) = qdecode(path[pos+1:], valid_daynum, salt) + if err != '': + phost = err else: str = path[pos+1:] if str == '': - return '', 0 - phost = '' - phost = str.split(':')[0] - pport = int(str.split(':')[1]) + return phost, 0 + part_list = str.split(':') + phost = part_list[0] + pport = int(part_list[1]) + if len(part_list) > 2: + username = part_list[2] + # check the access ability. + if not group.can_access(username, phost, gpolicy): + return 'Err: group policy block', 0 except: - return phost, 0 + raise + #return phost, 0 return phost, pport def test_basic(): @@ -66,23 +83,45 @@ def test_basic(): enc = qencode(str) print enc print base64.urlsafe_b64decode(enc) - dec = qdecode(enc) + (dec,err) = qdecode(enc) assert str == dec assert get_server_from_path('/'+enc, True) == ('n1.soc.cloud.ncl.sg', 5901) enc = qencode(str, datetime.date(2018, 2, 24)) - assert (get_server_from_path('/'+enc, True)) == ('', 0) + assert (get_server_from_path('/'+enc, True)) == ('Err: Timeout', 0) enc = qencode(str, datetime.date.today(), 'test salt') - dec = qdecode(enc, 3, 'test salt') + (dec,err) = qdecode(enc, 3, 'test salt') assert str == dec - dec = qdecode(enc, 3, 'test salt1') + (dec,err) = qdecode(enc, 3, 'test salt1') assert dec == '' str = "n1.soc.cloud.ncl.sg:5901:ntechni3" enc = qencode(str) print enc print base64.urlsafe_b64decode(enc) - dec = qdecode(enc) + (dec,err) = qdecode(enc) assert str == dec assert get_server_from_path('/'+enc, True) == ('n1.soc.cloud.ncl.sg', 5901) + (dec,err) = qdecode(enc + '/') + assert str == dec + gpolicy = { + "ExperimentDomainName":"soc.cloud.ncl.sg", + 'Groups':[{ + 'Name':'Red', + 'Users': ["user1", "ntechni3"], + 'Hosts': ["n1"] + }, + { + 'Name':'Blue', + 'Users': ['user1'], + 'Hosts': ['n2','n3'] + }] + } + str = "n1.soc.cloud.ncl.sg:5901:ntechni3" + enc = qencode(str) + assert get_server_from_path('/'+enc, True, 3, SALT, gpolicy) == ('n1.soc.cloud.ncl.sg', 5901) + str = "n2.soc.cloud.ncl.sg:5901:ntechni3" + enc = qencode(str) + assert get_server_from_path('/'+enc, True, 3, SALT, gpolicy) == ('Err: group policy block', 0) + def main(): '''The func is the main func.''' import sys @@ -93,11 +132,12 @@ def main(): elif (len(sys.argv) == 2): print qencode(sys.argv[1]) elif (len(sys.argv) == 3) and (sys.argv[1] == "decode"): - print qdecode(sys.argv[2]) + print get_server_from_path(sys.argv[2], True) + #print qdecode(sys.argv[2]) elif (len(sys.argv) == 5) and (sys.argv[1] == "decode"): - print qdecode(sys.argv[2],sys.argv[3],sys.argv[4]) + print qdecode(sys.argv[2],int(sys.argv[3]),sys.argv[4]) elif (len(sys.argv) == 5) and (sys.argv[1] == "encode"): - print qencode(sys.argv[2],sys.argv[3],sys.argv[4]) + print qencode(sys.argv[2],int(sys.argv[3]),sys.argv[4]) elif (len(sys.argv) == 3) and (sys.argv[1] == "debase"): str1 = base64.urlsafe_b64decode(sys.argv[2]) print str1 diff --git a/websockify/group.py b/websockify/group.py new file mode 100644 index 0000000..3800ee1 --- /dev/null +++ b/websockify/group.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python +import subprocess + +gpolicy = { } + +def group(users, hosts, ousers, ohosts): + '''The func handle group policy for one group. Users can access hosts.''' + pass +def get_users_hosts(gpolicy): + '''The func Get the all user list, hosts, hosts_access''' + users = set() + hosts = {} + hosts_access = {} + # Get the all user list, hosts, hosts_access + for group in gpolicy['Groups']: + if not group.has_key('Name'): + print "The group do not have key [Name]" + continue; + for user in group['Users']: + users.add(user) + if not hosts_access.has_key(user): + hosts_access[user] = set() + if group.has_key('Hosts'): + hosts_access[user] = hosts_access[user].union(group['Hosts']) + # get all host list. + if group.has_key('Hosts'): + for host in group['Hosts']: + hosts[host] = '' + return users, hosts, hosts_access +def get_super_users(gpolicy, users, hosts_access): + '''The func Get all super user list. User in super user list need be + deleted in user list and hosts_access.''' + super_users = set() + # Get all super user list. + for group in gpolicy['Groups']: + if not group.has_key('Name'): + print "The group do not have key [Name]" + continue; + if not group.has_key('Hosts'): + for user in group['Users']: + # Delete super user from normal user list. + if user in users: + users.remove(user) + del hosts_access[user] + super_users.add(user) + return (super_users, users, hosts_access) +def get_unaccess_hosts(hosts_access, hosts): + hosts_unaccess = {} + for user in hosts_access.keys(): + hosts_unaccess[user] = set() + for host in hosts: + if host not in hosts_access[user]: + hosts_unaccess[user].add(host) + return hosts_unaccess +def can_access(username, node_url, gpolicy): + '''The func return true or False, based on gpolicy allowing username to node_url or not.''' + if not gpolicy.has_key('ExperimentDomainName'): + print 'Err: no ExperimentDomainName' + return True + ename = gpolicy['ExperimentDomainName'] + exp_name = ename + dnode = node_url[:node_url.find('.')] + dexp = node_url[node_url.find('.')+1:] + if dexp != exp_name : + # not the experience group return true. + return True + for group in gpolicy['Groups']: + find_host = False + find_user = False + if not group.has_key('Name'): + print "The group do not have key [Name]" + continue; + if group.has_key('Hosts'): + for host in group['Hosts']: + if host == dnode: + find_host = True + else: + #super user group, can access all nodes. + find_host = True + if group.has_key('Users'): + for user in group['Users']: + if username == user: + find_user = True + if find_host and find_user : + return True + return False + +def group_exp(gpolicy): + ename = gpolicy['ExperimentDomainName'] + users = () + super_users = () + hosts = {} + hosts_access = {} + hosts_unaccess = {} + # Get the all user list, hosts, hosts_access + (users, hosts, hosts_access) = get_users_hosts(gpolicy) + # Get all super user list. + (super_users, users, hosts_access) = get_super_users(gpolicy, users, hosts_access) + # produce unaccess hosts for every user. + hosts_unaccess = get_unaccess_hosts(hosts_access, hosts) + + # For every normal user, get all accessable host list and give access right, other give no right. + for user in users: + for host in hosts_access[user]: + hosts[host] += 'sudo usermod -e "" %s\n' % user + for user in users: + for host in hosts_unaccess[user]: + hosts[host] += 'sudo usermod -e 1 %s\n' % user + # For every super user, give all access. + for user in super_users: + for host in hosts.keys(): + hosts[host] += 'sudo usermod -e "" %s\n' % user + return hosts +def test(): + gpolicy = { + "ExperimentDomainName":"EnterpriseNetwork.NYPSOC.ncl.sg", + 'Groups':[] + } + assert get_users_hosts(gpolicy) == (set([]), {}, {}) + + gpolicy = { + "ExperimentDomainName":"EnterpriseNetwork.NYPSOC.ncl.sg", + 'Groups':[{ + 'Name':'Red', + 'Users': ["user1", "user2"], + 'Hosts': ["n1"] + }, + { + 'Name':'Blue', + 'Users': ['user3'], + 'Hosts': ['n2','n3'] + }, + { + 'Name':'Grey', + 'Users': ['user4'], + 'Hosts': [] + }, + { + 'Name':'Super', + 'Users': ['user3'] + }] + } + (users, hosts, hosts_access) = get_users_hosts(gpolicy) + assert (users, hosts, hosts_access) == (set(['user4', 'user2', 'user3', 'user1']),\ + {'n1': '', 'n2': '', 'n3': ''}, \ + {'user4': set([]), 'user2': set(['n1']), 'user3': set(['n2', 'n3']), 'user1': set(['n1'])}) + assert get_unaccess_hosts(hosts_access, hosts) == { + 'user4': set(['n1', 'n2', 'n3']), 'user2': set(['n2', 'n3']), + 'user3': set(['n1']), 'user1': set(['n2', 'n3'])} + (super_users, users, hosts_access) = get_super_users(gpolicy, users, hosts_access) + assert (super_users, users, hosts_access) == (set(['user3']), + set(['user4', 'user2', 'user1']), \ + {'user4': set([]), 'user2': set(['n1']), 'user1': set(['n1'])}) + assert get_unaccess_hosts(hosts_access, hosts) == { + 'user4': set(['n1', 'n2', 'n3']), 'user2': set(['n2', 'n3']), + 'user1': set(['n2', 'n3'])} + print group_exp(gpolicy) + group_exp(gpolicy) == {'n1': 'sudo usermod -e "" user2\nsudo usermod -e "" user1\nsudo usermod -e 1 user4\nsudo usermod -e "" user3\n', 'n2': 'sudo usermod -e 1 user4\nsudo usermod -e 1 user2\nsudo usermod -e 1 user1\nsudo usermod -e "" user3\n', 'n3': 'sudo usermod -e 1 user4\nsudo usermod -e 1 user2\nsudo usermod -e 1 user1\nsudo usermod -e "" user3\n'} + + assert get_unaccess_hosts({'user1': set(['n1'])}, {'n1': ''}) == {'user1': set([])} + assert get_unaccess_hosts({'user1': set([])}, {'n1': ''}) == {'user1': set(['n1'])} + assert get_unaccess_hosts({'user1': set(['n1', 'n2'])}, {'n1': '', 'n2': ''}) == {'user1': set([])} + + gpolicy = { + "ExperimentDomainName":"EnterpriseNetwork.NYPSOC.ncl.sg", + 'Groups':[{ + 'Name':'Red', + 'Users': ["user1", "user2"], + 'Hosts': ["n1"] + }, + { + 'Name':'Blue', + 'Users': ['user1'], + 'Hosts': ['n2','n3'] + } ] + } + (users, hosts, hosts_access) = get_users_hosts(gpolicy) + #print (users, hosts, hosts_access) + assert (users, hosts, hosts_access) == (set(['user2', 'user1']), \ + {'n1': '', 'n2': '', 'n3': ''}, {'user2': set(['n1']), 'user1': set(['n1', 'n2', 'n3'])}) + gpolicy = { + "ExperimentDomainName":"EnterpriseNetwork.NYPSOC.ncl.sg", + 'Groups':[{ + 'Name':'Red', + 'Users': ["user1", "user2"], + 'Hosts': ["n1"] + }, + { + 'Name':'Blue', + 'Users': ['user1'], + 'Hosts': ['n2','n3'] + }, + { 'Name':'superusers', 'Users':['suser']} + ] + } + assert can_access('user1', 'n1.EnterpriseNetwork.NYPSOC.ncl.sg', gpolicy) == True + assert can_access('user1', 'n1.another.NYPSOC.ncl.sg', gpolicy) == True + assert can_access('user1', 'n2.EnterpriseNetwork.NYPSOC.ncl.sg', gpolicy) == True + assert can_access('user2', 'n2.EnterpriseNetwork.NYPSOC.ncl.sg', gpolicy) == False + assert can_access('user3', 'n2.EnterpriseNetwork.NYPSOC.ncl.sg', gpolicy) == False + assert can_access('suser', 'n2.EnterpriseNetwork.NYPSOC.ncl.sg', gpolicy) == True + + +def main(): + '''The func is the main func.''' + import sys + if (len(sys.argv) == 2) and (sys.argv[1] == "test"): + test() + print "Pass all test" + exit() + if (len(sys.argv) == 2) and (sys.argv[1] == "do"): + gp1 = { } + node_cmd_list = group_exp(gp1) + ename = gp1['ExperimentDomainName'] + + for (node, cmd) in node_cmd_list.items(): + cmdline = "echo '%s' | ssh %s.%s" % (cmd, node, ename) + subprocess.call(cmdline, shell = True) + +if __name__ == "__main__": + main() diff --git a/websockify/websocketproxy.py b/websockify/websocketproxy.py index 7adcd1f..3c72287 100644 --- a/websockify/websocketproxy.py +++ b/websockify/websocketproxy.py @@ -36,9 +36,9 @@ URL_PATH_DEF_VNCSERVER = True # Whether is URL path encoded URL_PATH_ENCODED = False # URL valid day number after creating. -URL_VALID_DAYNUM = 3 +URL_VALID_DAYNUM = 1 # Salt used to valide the hash of the URL. -URL_SALT = 'Some salt used to hash the URL for integrity validation. liqun@ncl.sg' +URL_SALT = "Some salt for security. Please change it in your project. liqun@ncl.sg" class ProxyRequestHandler(websockifyserver.WebSockifyRequestHandler): @@ -114,7 +114,9 @@ Traffic Legend: (ptarget_host, ptarget_port) = encode_url.get_server_from_path(\ self.path, URL_PATH_ENCODED, URL_VALID_DAYNUM, URL_SALT) if ptarget_port == 0: - raise self.server.EClose('Cannot decode path.') + print 'Error: URL encode error[%s]' % ptarget_host + return + #raise self.server.EClose('Cannot decode path.') msg = "connecting to: %s:%s" % (ptarget_host, ptarget_port) else: msg = "connecting to: %s:%s" % ( From 6f520ae63a8717095ebb0d838986f849ef3176f0 Mon Sep 17 00:00:00 2001 From: QunL Date: Tue, 24 Apr 2018 11:13:05 +0800 Subject: [PATCH 5/5] Update the feature --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 6755779..78a3bf6 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,9 @@ and websockify as a browser telnet client (`wstelnet.html`). These are not necessary for the basic operation. +* Muliti-vncserver: Use path in URL to pass VNC server address:port for + connecting different VNC servers. + * Daemonizing: When the `-D` option is specified, websockify runs in the background as a daemon process.