Added first part of the RFC1149 implementation
This commit is contained in:
parent
b9a96f6bc4
commit
7899846338
|
@ -0,0 +1,7 @@
|
|||
|
||||
|
||||
Installation
|
||||
============
|
||||
You need
|
||||
* tweepy >= 1.8 (https://github.com/tweepy/tweepy.git)
|
||||
* python-bytearray
|
|
@ -0,0 +1,35 @@
|
|||
# ___________________________________________________
|
||||
# | |
|
||||
# | ircvpn - irc virtual public network configuration |
|
||||
# |___________________________________________________|
|
||||
|
||||
import os
|
||||
|
||||
Conf = {
|
||||
# ======== network settings ========
|
||||
# ipsettings for the device
|
||||
'devname': '',
|
||||
'network':
|
||||
{
|
||||
'address': '10.10.10.74',
|
||||
'netmask': '255.255.255.0',
|
||||
#gateway: '',
|
||||
'mtu': 1400,
|
||||
},
|
||||
|
||||
# ======== Twitter settings ========
|
||||
'twitter':
|
||||
{
|
||||
# account to read network traffic from
|
||||
'endpoint': None,
|
||||
|
||||
# if set to None, these will be overwritten by config_auth.py
|
||||
# if they are set to none there, this script will give you an
|
||||
# url to authorize this script to twitter and write the
|
||||
# access key / access secret to config_auth.py
|
||||
'ACCESS_KEY': None,
|
||||
'ACCESS_SECRET': None,
|
||||
},
|
||||
}
|
||||
|
||||
import conf_auth
|
|
@ -0,0 +1,7 @@
|
|||
from conf import Conf
|
||||
|
||||
# WARNING: This config will be overwritten if you use the scripts internal
|
||||
# way to get an access key.
|
||||
if not Conf['twitter']['ACCESS_KEY']:
|
||||
Conf['twitter']['ACCESS_KEY'] = None
|
||||
Conf['twitter']['ACCESS_SECRET'] = None
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import base64
|
||||
import logging
|
||||
import math
|
||||
import re
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import tweepy
|
||||
from uphelper import UPHelper
|
||||
|
||||
sys.path.append("../../../")
|
||||
|
||||
from conf import Conf
|
||||
from ether2any import Ether2Any
|
||||
from ether2any.helper import getDstMacFromPkt, isBroadcast, binToHexStr
|
||||
|
||||
class TwittStreamHandler(tweepy.StreamListener):
|
||||
def __init__(self, dev):
|
||||
super(TwittStreamHandler, self).__init__()
|
||||
self.dev = dev
|
||||
self.fragments = {}
|
||||
|
||||
def on_status( self, status ):
|
||||
print '-' * 20
|
||||
print "incoming:", unicode(status.text)
|
||||
print "hex:", binToHexStr(status.text), len(status.text)
|
||||
# reassemble messages, put them together if nessecary.
|
||||
|
||||
def on_limit(self, track):
|
||||
print "We got limited ", track
|
||||
print "At the moment there is no error-handling for this, so we just kill everything. Remember: This software doesn't even deserve the label 'alpha' ;)"
|
||||
sys.exit(1)
|
||||
|
||||
def on_error(self, status_code):
|
||||
print "We got an error code: ", status_code
|
||||
if status_code == 401:
|
||||
print "Better check 'yer twitter-credentials."
|
||||
sys.exit(2)
|
||||
else:
|
||||
print "At the moment there is no error-handling for this, so we just kill everything. Remember: This software doesn't even deserve the label 'alpha' ;)"
|
||||
sys.exit(1)
|
||||
|
||||
def on_timeout(self, status_code):
|
||||
print "Got an timeout: ", status_code
|
||||
print "At the moment there is no error-handling for this, so we just kill everything. Remember: This software doesn't even deserve the label 'alpha' ;)"
|
||||
|
||||
class DownstreamThread(threading.Thread):
|
||||
def __init__(self, dev, auth, endpoint):
|
||||
threading.Thread.__init__(self)
|
||||
self.auth = auth
|
||||
self.endpoint = endpoint
|
||||
self.dev = dev
|
||||
self.daemon = True
|
||||
|
||||
def run(self):
|
||||
stream = tweepy.Stream(auth=self.auth, listener=TwittStreamHandler(self.dev))
|
||||
stream.userstream()
|
||||
stream.filter(self.endpoint, None)
|
||||
stream.sample()
|
||||
|
||||
class RFC1149(Ether2Any):
|
||||
def __init__(self):
|
||||
Ether2Any.__init__(self, tap=False)
|
||||
|
||||
network = Conf.get("network", {'mtu': 1400})
|
||||
self.twitterConf = Conf.get("twitter", None)
|
||||
self.endpoint = self.twitterConf['endpoint']
|
||||
if not self.endpoint:
|
||||
print "No endpoint in configuration, please add one."
|
||||
sys.exit(1)
|
||||
self.dev.ifconfig(**network)
|
||||
self.dev.up()
|
||||
|
||||
self._setupTwitter()
|
||||
self.downstream = DownstreamThread(dev=self.dev, auth=self.auth, endpoint=self.endpoint)
|
||||
self.downstream.start()
|
||||
|
||||
def _requestTwitterTokens(self):
|
||||
auth = tweepy.OAuthHandler(self._dec(self.ck), self._dec(self.cs))
|
||||
pass
|
||||
|
||||
def _setupTwitter(self):
|
||||
ck = [17, 39, 65, 39, 25, 22, 38, 30, 20, 38, 33, 69, 27, 0, 61,
|
||||
31, 61, 34, 42, 32]
|
||||
cs = [71, 37, 71, 37, 57, 36, 18, 2, 59, 64, 63, 58, 23, 61, 74,
|
||||
30, 34, 68, 38, 33, 56, 1, 3, 74, 29, 9, 41, 32, 33, 7, 52,
|
||||
8, 70, 20, 30, 25, 38, 51, 57, 66, 53, 0, 42]
|
||||
self.auth = tweepy.OAuthHandler(self._dec(ck), self._dec(cs))
|
||||
if not self.twitterConf['ACCESS_KEY']:
|
||||
# request tokens, get access, write tokens down.
|
||||
auth_url = self.auth.get_authorization_url()
|
||||
print "We have no access token for a twitter account. Please visit the"
|
||||
print "url printed down below, login and report back with the PIN."
|
||||
print
|
||||
print " Authorization URL: %s" % auth_url
|
||||
print
|
||||
verifier = raw_input('PIN: ').strip()
|
||||
self.auth.get_access_token(verifier)
|
||||
self.twitterConf['ACCESS_KEY'] = self.auth.access_token.key
|
||||
self.twitterConf['ACCESS_SECRET'] = self.auth.access_token.secret
|
||||
authConf = open("conf_auth.py", "w")
|
||||
authConf.write("""from conf import Conf
|
||||
|
||||
# WARNING: This config was overwritten! If you change it be sure
|
||||
# that you know, what you are doing.
|
||||
if not Conf['twitter']['ACCESS_KEY']:
|
||||
Conf['twitter']['ACCESS_KEY'] = "%s"
|
||||
Conf['twitter']['ACCESS_SECRET'] = "%s"
|
||||
""" % (self.twitterConf['ACCESS_KEY'], self.twitterConf['ACCESS_SECRET']))
|
||||
authConf.close()
|
||||
self.auth.set_access_token(self.twitterConf['ACCESS_KEY'], self.twitterConf['ACCESS_SECRET'])
|
||||
self.api = tweepy.API(self.auth)
|
||||
|
||||
def _dec(self, s):
|
||||
""" ... """
|
||||
return "".join(map(lambda x: chr(x+48), reversed(s)))
|
||||
|
||||
def sendToNet(self, packet):
|
||||
for subPacket in UPHelper.encode(packet):
|
||||
print subPacket
|
||||
|
||||
if __name__ == '__main__':
|
||||
rfc = RFC1149()
|
||||
print "Starting RFC1149 ip-over-twitter service..."
|
||||
rfc.run()
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import random
|
||||
import bitarray
|
||||
|
||||
class UPHelper():
|
||||
""" The Unicode Packet Helper
|
||||
|
||||
Twitter supports 140 chars, while a char can be a unicode
|
||||
character. For a unicode character there are 2^20 possibilities.
|
||||
For the sake of lazyness we put two bytes in each character, using
|
||||
only 2^16. The remaining 4 bits can be used for metadata or whatever.
|
||||
|
||||
The header in the metadata is as following:
|
||||
<fragment bit (1 if packet is a fragment, 0 if last in row)>
|
||||
<9 bits length of payload>
|
||||
<32 bit random paket id>"""
|
||||
|
||||
@staticmethod
|
||||
def intToBits(n, length):
|
||||
""" Convert the number n to a bitarray of length. """
|
||||
i = 0
|
||||
c = 1
|
||||
ret = [False] * length
|
||||
while i < length:
|
||||
ret[length-(i+1)] = (n & c) > 0
|
||||
i += 1
|
||||
c <<= 1
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def bitsToInt(bits):
|
||||
ret = 0
|
||||
for i in bits:
|
||||
ret = (ret << 1) | (i and 1 or 0)
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def encode(data):
|
||||
""" Generate list of packets with a header from data. """
|
||||
packetId = random.randint(0, 2**32)
|
||||
fragments = []
|
||||
while len(data) > 280:
|
||||
fragments.append(data[0:280])
|
||||
data = data[280:]
|
||||
if len(data) > 0:
|
||||
fragments.append(data)
|
||||
|
||||
# convert to twitter message
|
||||
for y in range(len(fragments)):
|
||||
fragment = fragments[y]
|
||||
lenX = len(fragment)
|
||||
# pad packet if it is not long enouth / not aligned
|
||||
if len(fragment) < 2*11:
|
||||
fragment = fragment + "\x00" * (2*11-len(fragment))
|
||||
if len(fragment) % 2 == 1:
|
||||
fragment += "\x00"
|
||||
|
||||
# write header (bits: 1 fragment, 9 length, 32 id)
|
||||
header = bitarray.bitarray(1)
|
||||
# write fragment-bit
|
||||
header[0] = (y+1 == len(fragments))
|
||||
# append packet length
|
||||
header.extend(UPHelper.intToBits(lenX, 9))
|
||||
# add packet id
|
||||
header.extend(UPHelper.intToBits(packetId, 32))
|
||||
# padding to complete last 4 bytes
|
||||
header.extend([False, False])
|
||||
|
||||
i = 0
|
||||
h = 0
|
||||
ret = ""
|
||||
while i+1 < len(fragment):
|
||||
val = ord(fragment[i]) << 8 | ord(fragment[i+1])
|
||||
if h < 11:
|
||||
val |= UPHelper.bitsToInt(header[h*4:(h+1)*4]) << 16
|
||||
h += 1
|
||||
ret += unichr(val)
|
||||
i += 2
|
||||
fragments[y] = ret
|
||||
return fragments
|
||||
|
||||
@staticmethod
|
||||
def decode(packet):
|
||||
""" Decodes an unicodestring (packet) back to header + data
|
||||
|
||||
Returns: tupel(isFragmented, packetLen, packetId, data) """
|
||||
if len(packet) < 11:
|
||||
raise ValueError("This is not a valid packet, header is too short (should be at least 11, is %d)" % len(packet))
|
||||
header = bitarray.bitarray()
|
||||
for i in range(11):
|
||||
header.extend("{:04b}".format(ord(packet[i]) >> 16))
|
||||
isFragmented = header[0]
|
||||
|
||||
packetLen = UPHelper.bitsToInt(header[1:9])
|
||||
packetId = UPHelper.bitsToInt(header[9:])
|
||||
rawData = map(lambda x: ord(x) & 0xFFFF, packet)
|
||||
data = []
|
||||
for p in rawData:
|
||||
data.append(chr(p >> 8))
|
||||
data.append(chr(p & 255))
|
||||
data = "".join(data)
|
||||
|
||||
return (isFragmented, packetLen, packetId, data)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print UPHelper.encode("foo")
|
||||
print UPHelper.decode(UPHelper.encode("foo")[0])
|
||||
msg = "".join([chr(i) for i in range(256)])
|
||||
msg += "".join([chr(i) for i in range(256)])
|
||||
p = UPHelper.encode(msg)
|
||||
print repr(msg)
|
||||
for x in p:
|
||||
print UPHelper.decode(x)
|
||||
|
Loading…
Reference in New Issue