def hasReceivedPing(self, timeout=1.0): """ Waits to receive "ping" event until the end of the timeout. @param timeout: time to wait response in second (default=1s) @type timeout: float @return: an event matching with the template or None otherwise @rtype: templatemessage """ TestAdapterLib.check_timeout(caller=TestAdapterLib.caller(), timeout=timeout) tpl_rsp = TestTemplatesLib.TemplateMessage() if self.cfg['agent-support']: layer_agent = TestTemplatesLib.TemplateLayer('AGENT') layer_agent.addKey(name='name', data=self.cfg['agent']['name']) layer_agent.addKey(name='type', data=self.cfg['agent']['type']) tpl_rsp.addLayer(layer_agent) tpl_rsp.addLayer(AdapterIP.ip(more=AdapterIP.received())) tpl_rsp.addLayer(AdapterTCP.tcp(more=AdapterTCP.received())) if self.cfg['ssl-support']: tpl_rsp.addLayer(AdapterSSL.ssl(more=AdapterSSL.received())) tpl_rsp.addLayer( templates.ws(opcode=codec.WEBSOCKET_OPCODE_PING, more=templates.received())) return self.received(expected=tpl_rsp, timeout=timeout)
def isHandshakeSuccessful(self, timeout=1.0): """ Wait to receive "handshake successful" event until the end of the timeout. @param timeout: time to wait response in second (default=1s) @type timeout: float @return: an event matching with the template or None otherwise @rtype: templatemessage """ TestAdapterLib.check_timeout(caller=TestAdapterLib.caller(), timeout=timeout) tpl_rsp = TestTemplatesLib.TemplateMessage() if self.cfg['agent-support']: layer_agent = TestTemplatesLib.TemplateLayer('AGENT') layer_agent.addKey(name='name', data=self.cfg['agent']['name']) layer_agent.addKey(name='type', data=self.cfg['agent']['type']) tpl_rsp.addLayer(layer_agent) tpl_rsp.addLayer(AdapterIP.ip(more=AdapterIP.received())) tpl_rsp.addLayer(AdapterTCP.tcp(more=AdapterTCP.received())) if self.cfg['ssl-support']: tpl_rsp.addLayer(AdapterSSL.ssl(more=AdapterSSL.received())) tpl_rsp.addLayer(AdapterHTTP.response()) tpl_rsp.addLayer(templates.ws(more=templates.handshake_ok())) return self.received(expected=tpl_rsp, timeout=timeout)
def sendBinary(self, data): """ Send binary data @param data: data to send @type data: string """ if not self.wsHanshakeSuccess: return # make chunk chunks = [ data[x:x + self.wsMaxPayloadSize] for x in xrange(0, len(data), self.wsMaxPayloadSize) ] # encode data in the websocket packet and enqueue it for chunk in chunks: ws_tpl = templates.ws(fin=1, mask=0, rsv1=0, rsv2=0, rsv3=0, opcode=codec.WEBSOCKET_OPCODE_BINARY, data=chunk, data_length=len(chunk), more=templates.sent()) wsdata = self.wsCodec.encodeWsData(tpl=ws_tpl) # Send websocket data try: lower = self.ADP_HTTP.tcp().sendData(data=wsdata) except Exception as e: #raise Exception("send request: tcp failed: %s" % str(e)) raise TestAdapterLib.AdapterException( TestAdapterLib.caller(), "send request: tcp failed: %s" % str(e)) lower.addLayer(ws_tpl) # Log event if self.logEventSent: lower.addRaw(raw=wsdata) self.logSentEvent(shortEvt=codec.WEBSOCKET_OPCODE_BINARY_STR, tplEvt=lower)
def sendRaw(self, opcode=0, fin=1, mask=0, rsv1=0, rsv2=0, rsv3=0, data=''): """ Send raw data """ if not self.wsHanshakeSuccess: return ws_tpl = templates.ws(fin=fin, mask=mask, rsv1=rsv1, rsv2=rsv2, rsv3=rsv3, opcode=opcode, data=data, data_length=len(data), more=templates.sent()) wsdata = self.wsCodec.encodeWsData(tpl=ws_tpl) # Send websocket data try: lower = self.ADP_HTTP.tcp().sendData(data=wsdata) except Exception as e: #raise Exception("send request: tcp failed: %s" % str(e)) raise TestAdapterLib.AdapterException( TestAdapterLib.caller(), "send request: tcp failed: %s" % str(e)) lower.addLayer(ws_tpl) # Log event if self.logEventSent: lower.addRaw(raw=wsdata) self.logSentEvent(shortEvt=codec.WEBSOCKET_OPCODE_TEXT_STR, tplEvt=lower)
def sendPong(self, data=None): """ Send pong @param data: data included on the pong (default=None) @type data: string """ if data is None: dataLength = 0 else: dataLength = len(data) ws_tpl = templates.ws(fin=1, mask=0, rsv1=0, rsv2=0, rsv3=0, opcode=codec.WEBSOCKET_OPCODE_PONG, data=data, data_length=dataLength, more=templates.sent()) wsdata = self.wsCodec.encodeWsData(tpl=ws_tpl) # Send websocket data try: lower = self.ADP_HTTP.tcp().sendData(data=wsdata) except Exception as e: #raise Exception("send request: tcp failed: %s" % str(e)) raise TestAdapterLib.AdapterException( TestAdapterLib.caller(), "send request: tcp failed: %s" % str(e)) lower.addLayer(ws_tpl) # Log event if self.logEventSent: lower.addRaw(raw=wsdata) self.logSentEvent(shortEvt=codec.WEBSOCKET_OPCODE_PONG_STR, tplEvt=lower)
def handshake(self, resource, origin): """ Do hanshake """ self.wsHanshakeSuccess = False self.wsKey = self.wsCodec.createSecWsKey() req = ["GET %s HTTP/1.1" % resource] req.append("Upgrade: websocket") req.append("Connection: keep-alive, upgrade") req.append("Host: %s" % self.cfg['dest-ip']) req.append("Origin: http://%s" % origin) req.append("Sec-WebSocket-Key: %s" % self.wsKey) req.append("Sec-WebSocket-Version: %s" % codec.WEBSOCKET_VERSION) req.append("") req_tpl = self.ADP_HTTP.constructTemplateRequest(rawHttp=req) lower_tpl = self.ADP_HTTP.sendRequest(tpl=req_tpl) if self.logEventSent: tpl = templates.ws(more=templates.handshake()) lower_tpl.addLayer(tpl) self.logSentEvent(shortEvt='Handshake', tplEvt=lower_tpl)
def handleIncomingHttpResponse(self, data, lower): """ On http response """ http_rsp = lower.get('HTTP', 'response') http_hdrs = lower.get('HTTP', 'headers') http_code = http_rsp.get('code') if str(http_code) != '101': if self.logEventReceived: tpl = templates.ws(more=templates.handshake_error( details="bad http response: %s" % http_code)) lower.addLayer(tpl) self.logRecvEvent(shortEvt='Handshake Error', tplEvt=lower) else: self.error('hanshake failed bad http response: %s' % http_code) else: # decode specific ws headers hdrUpgrade = False hdrConnection = False wsAccept = False try: for k, v in http_hdrs.getItems(): if k.lower().strip() == 'upgrade' and v.lower().strip( ) == 'websocket': hdrUpgrade = True if k.lower().strip() == 'connection' and v.lower().strip( ) == 'upgrade': hdrConnection = True if k.lower().strip() == 'sec-websocket-accept': v = v.lower().strip() # rfc6455 1.3. Opening Handshake value = (self.wsKey + codec.GUID).encode('utf-8') sha1 = sha1_constructor() sha1.update(value) hashed = base64.encodestring( sha1.digest()).strip().lower() if hashed == v: wsAccept = True else: if self.logEventReceived: tpl = templates.ws( more=templates.handshake_error( details= "key incorrect computed=%s received=%s key=%s" % (hashed, v, self.wsKey))) lower.addLayer(tpl) self.logRecvEvent(shortEvt='Handshake Error', tplEvt=lower) else: self.error( 'web socket key incorrect computed=%s received=%s key=%s' % (hashed, v, self.wsKey)) except Exception as e: self.error('unable to check websocket headers: %s' % e) else: if hdrUpgrade and hdrConnection and wsAccept: self.wsHanshakeSuccess = True if self.logEventReceived: tpl = templates.ws(more=templates.handshake_ok()) lower.addLayer(tpl) self.logRecvEvent(shortEvt='Handshake OK', tplEvt=lower) else: self.info('handshake ok') self.ADP_HTTP.activeWebsocket() else: if self.logEventReceived: tpl = templates.ws(more=templates.handshake_error()) lower.addLayer(tpl) self.logRecvEvent(shortEvt='Handshake Error', tplEvt=lower) else: self.error('hanshake failed')
def decodeWsData(self, buffer): """ Decode ws message @param buffer: buffer @type buffer: string """ tpl = None payload = '' opcode = None left = '' needMore = False try: try: hdrs_len = 2 # B = 1 octet # H = 2 octets # I = 4 octets fixed_hdr = struct.unpack('!2B', buffer[:hdrs_len]) remaining = buffer[hdrs_len:] except struct.error as e: left = buffer # need more data needMore = True self.debug("ws need more data in header") else: fin = fixed_hdr[0] >> 7 & 1 rsv1 = fixed_hdr[0] >> 6 & 1 rsv2 = fixed_hdr[0] >> 5 & 1 rsv3 = fixed_hdr[0] >> 4 & 1 opcode = fixed_hdr[0] & 0xf has_mask = fixed_hdr[1] >> 7 & 1 length = fixed_hdr[1] & 0x7f self.debug("ws header: %s, %s, %s, %s, %s, %s, %s" % (fin, rsv1, rsv2, rsv3, opcode, has_mask, length)) if length == 126: try: hdrs_extended_len = 2 size = buffer[hdrs_len:hdrs_len + hdrs_extended_len] ext_lenght_hdr = struct.unpack( '!H', buffer[hdrs_len:hdrs_len + hdrs_extended_len]) except struct.error as e: left = buffer # need more data needMore = True self.debug("ws need more data in data") else: length_ext = ext_lenght_hdr[0] self.debug("ws lenght extended: %s" % length_ext) if fin: if len( buffer ) < hdrs_len + hdrs_extended_len + length_ext: self.debug( "data extended, need more data (%s/%s)" % (len(buffer), length_ext)) left = buffer # need more data needMore = True else: payload = buffer[hdrs_len + hdrs_extended_len:hdrs_len + hdrs_extended_len + length_ext] left = buffer[hdrs_len + hdrs_extended_len + length_ext:] else: left = buffer # need more data needMore = True else: if fin: if len(buffer) < hdrs_len + length: self.debug( "fin=1 but insufficient data in buffer, need more (%s/%s)" % (len(buffer), length)) left = buffer # need mode data needMore = True else: payload = buffer[hdrs_len:hdrs_len + length] left = buffer[hdrs_len + length:] else: self.debug("ws need more data fin=0") left = buffer # need mode data needMore = True if not needMore: self.debug('decode complete') tpl = templates.ws(fin=fin, mask=has_mask, rsv1=rsv1, rsv2=rsv2, rsv3=rsv3, opcode=opcode, data=payload, data_length=len(payload), more=templates.received()) tpl.addRaw(buffer) except Exception as e: self.error('unable to decode ws data: %s' % e) return (payload, left, needMore, tpl)