Advertisement
Guest User

handshake

a guest
Jul 14th, 2010
308
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.60 KB | None | 0 0
  1. # module ws_utils.py
  2. # Joshua Marshall Moore
  3. # 7/14/2010
  4.  
  5. def getHeaderValue(request, header):
  6.     """ Returns the value of a header specified header field. """
  7.     delim = ': '
  8.     start = request.index(header.strip() + ': ')
  9.     end = request.index('\r\n', start)
  10.     return request[start+len(header)+len(delim):end]
  11.  
  12. def handshake(s):
  13.     request = s.recv(1024)
  14.  
  15.     print 'Request: \n', request, 'END\n'
  16.  
  17.     # skip: 1. If the user agent already has a websocket connection to the remote host (IP address) identified by host even if known by another name, wait until that connection has been established or for that connection to have failed.
  18.     # 2. establish the following information
  19.  
  20.     # hostname or ip address of the websocket server, as it is to be addressed by clients.
  21.     host = ' localhost'
  22.  
  23.     # the port number on which the server expected and/or received the connection
  24.     port = 8888
  25.  
  26.     # an identifier for hte service provided by the server. if the server provides multiple services, then the value should be derived from the resource name given in hte client's handshake
  27.     resource_name = ''
  28.  
  29.     # true if the connection is encrypted or if the server expected it to be encrypted; false otherwise
  30.     secure_flag = False
  31.  
  32.     # the asci serialization of the origin that the server is willing to communicate with, converted to ascii lowercase.
  33.     origin = getHeaderValue(request, "Origin").lower()
  34.  
  35.     # either null, or a string representing the subprotocol the server is ready to use. if the server supports multipe subprotocls then the value should be derived from the client's handshake, specifically from the "Sec-WebSocket-Protocol" field. The absence of such a field is equivalent to the null value. The empty string is not the same as the null value for these purposes
  36.     subprotocol = 'null'
  37.  
  38.     # the value of the "Sec-WebSocket_Key1" field in the client's handshake
  39.     key_1 = getHeaderValue(request, 'Sec-WebSocket-Key1')
  40.  
  41.     # the value of the "Sec-WebSocket-Key2" field in the client's handshake
  42.     key_2 = getHeaderValue(request, 'Sec-WebSocket-Key2')
  43.  
  44.     # the eight random bytes sent after the first 0x0D 0x0A 0x0D 0x0A sequence in the client's handshake
  45.     key_3 = request[-8:]
  46.  
  47.     # 3. Let location be the string that results from construct a websocket URL from host, port resource name and secure flag
  48.     location = "ws://localhost:8888/"
  49.  
  50.     # 4. Let key-number_1 be the digits in key1 be the digits in key_1, interpreted as a base ten integer ignoring all other characters in key1
  51.     keynumber_1 = ""
  52.     for char in key_1:
  53.         if char.isdigit():
  54.             keynumber_1 += char
  55.     keynumber_1 = int(keynumber_1)
  56.  
  57.     # similar for key-number_2
  58.     keynumber_2 = ""
  59.     for char in key_2:
  60.         if char.isdigit():
  61.             keynumber_2 += char
  62.     keynumber_2 = int(keynumber_2)
  63.  
  64.     # Let spaces_1 be the number of SPACE characters in key1
  65.     spaces_1 = 0
  66.     for char in key_1:
  67.         if char is ' ':
  68.             spaces_1 += 1
  69.  
  70.     # 5. Let spaces_2 be the number of SPACE characters in key2
  71.     spaces_2 = 0
  72.     for char in key_2:
  73.         if char is ' ':
  74.             spaces_2 += 1
  75.  
  76.     # If either spaces_1 or spaces_2 is zero, then abort the WebSocket connection. This is a symptom of a cross-protocol attak
  77.     if not spaces_1 or not spaces_2:
  78.         s.close()
  79.         return False
  80.  
  81.     # 6. if key-number_1 is not an integral multiple of spaces_1 then abort the websocket connection
  82.     if keynumber_1 % spaces_1 or keynumber_2 % spaces_2:
  83.         s.close
  84.         return False
  85.  
  86.     # 7. Let part one bw key-number_1 divided by spaces_1
  87.     part_1 = keynumber_1 / spaces_1
  88.     part_2 = keynumber_2 / spaces_2
  89.  
  90.     # 8. Let challenge be the concatenation of part_1, expressed as a big-endian 32bit integer, part_2, expressed as a big endian 32bit integer and the eight bytes of key3 in the order they were sent on the wire
  91.     index_key1 = request.index("Sec-WebSocket-Key1: ")
  92.     index_key2 = request.index("Sec-WebSocket-Key2: ")
  93.     challenge = ''
  94.     if index_key1 < index_key2:
  95.         challenge = str(part_1) + str(part_2) + key_3
  96.     else:
  97.         challenge = str(part_2) + str(part_1) + key_3
  98.  
  99.     # 9. Let response be the md5 fingerprint of challenge as a big-endian 128 bit string
  100.     response = md5.new(challenge).digest()
  101.  
  102.     serverHandshake = ''
  103.  
  104.     # 10. Send the following line, termined by CRLF and encoded as UTF-8 to the client:
  105.     # s.send(u"HTTP/1.1 101 WebSocket Protocol Handshake")
  106.     serverHandshake += "HTTP/1.1 101 WebSocket Protocol Handshake"
  107.  
  108.     # 11. Send the following line to the client. each field must be sent as a line consisting of the field name, which must be an ASCII case insensitive match for the field name in the list below, followoed by a COLON and a SPACE character, followed by the field value as specified in the list below, followed by CRLF. The lines must be encoded as UTF-8
  109.     # s.send(u"Upgrade: Websocket\r\n")
  110.     # s.send(u"Sec-WebSocket-Location: %s\r\n" % location)
  111.     # s.send(u"Sec-WebSocket-Origin: %s\r\n" % origin)
  112.     # s.send(u"Sec-WebSocket-Protocol: %s" % subprotocol)
  113.     serverHandshake += "Upgrade: WebSocket\r\n"
  114.     serverHandshake += "Sec-WebSocket-Location: %s\r\n" % location
  115.     serverHandshake += "Sec-WebSocket-Origin: %s\r\n" % origin
  116.     serverHandshake += "Sec-WebSocket-Protocol: %s\r\n" % subprotocol
  117.    
  118.  
  119.     # 12. send CRLF
  120.     # s.send(u"\r\n")
  121.     serverHandshake += "\r\n"
  122.  
  123.     # 13. send response
  124.     # s.send(response)
  125.     serverHandshake += response
  126.  
  127.     unicodeString = unicode(serverHandshake, "utf-8")
  128.     s.send(unicodeString)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement