parent
104cc5166a
commit
1db64fe052
@ -1 +1,2 @@ |
|||||||
*~ |
*~ |
||||||
|
*.pyc |
||||||
|
|||||||
@ -0,0 +1,67 @@ |
|||||||
|
#!/usr/bin/python |
||||||
|
|
||||||
|
import xmpp, os, hashlib, time |
||||||
|
from datetime import datetime |
||||||
|
|
||||||
|
ID=0 |
||||||
|
|
||||||
|
JINGLE_NS = 'urn:xmpp:jingle:1' |
||||||
|
JINGLE_FT_NS = 'urn:xmpp:jingle:apps:file-transfer:3' |
||||||
|
JINGLE_TRANSPORT_S5B_NS = 'urn:xmpp:jingle:transports:s5b:1' |
||||||
|
HASHES_NS = 'urn:xmpp:hashes:1' |
||||||
|
|
||||||
|
|
||||||
|
def create_init_message(mfrom,to,path,desc,host,port): |
||||||
|
global ID |
||||||
|
ID+=1 |
||||||
|
iq=xmpp.Iq(xmlns=None, |
||||||
|
attrs={'to':to,'id':"jin_ft_iq_%d" % ID,'type':'set'}) |
||||||
|
jingle=__create_jingle_node(mfrom,'session-initiate',"jin_ft_%d" % ID) |
||||||
|
iq.getChildren().append(jingle) |
||||||
|
|
||||||
|
cont=__create_content_node('initiator',time.time(),path,desc) |
||||||
|
jingle.getChildren().append(cont) |
||||||
|
tr = __create_transport_tcp_direct(mfrom,host,port,126<<8+127,ID) |
||||||
|
cont.getChildren().append(tr) |
||||||
|
return iq |
||||||
|
|
||||||
|
def __create_jingle_node(initiator,action,sid): |
||||||
|
return xmpp.Protocol(name="jingle",xmlns=JINGLE_NS, |
||||||
|
attrs={'initiator':initiator,'action':action,'sid':sid}) |
||||||
|
|
||||||
|
|
||||||
|
def __create_content_node(creator,date,path,txt): |
||||||
|
mfile=open(path,"r") |
||||||
|
datefmt = datetime.fromtimestamp(date).strftime("%Y-%m-%dT%H:%M:%SZ") |
||||||
|
name=os.path.basename(path) |
||||||
|
size=os.path.getsize(path) |
||||||
|
mhash=hashlib.sha1() |
||||||
|
mhash.update(mfile.read()) |
||||||
|
mfile.close() |
||||||
|
|
||||||
|
cont= xmpp.Protocol(name="content",attrs={'creator':creator,'name':name}) |
||||||
|
desc = cont.addChild(name="description",namespace=JINGLE_FT_NS) |
||||||
|
offer = desc.addChild(name="offer") |
||||||
|
mfile = offer.addChild(name="file") |
||||||
|
|
||||||
|
mfile.addChild(name="date",payload=[datefmt]) |
||||||
|
mfile.addChild(name="desc",payload=[txt]) |
||||||
|
mfile.addChild(name="name",payload=[name]) |
||||||
|
mfile.addChild(name="size",payload=[size]) |
||||||
|
mfile.addChild(name="hash",payload=[mhash.hexdigest()], |
||||||
|
attrs={'algo':'sha-1'},namespace=HASHES_NS) |
||||||
|
|
||||||
|
return cont |
||||||
|
|
||||||
|
def __create_transport_tcp_direct(mfrom,host,port,priority,id): |
||||||
|
tr = xmpp.Protocol(name="transport", |
||||||
|
attrs={'mode':'tcp','sid':"jin_ft_tr_%d" % id}) |
||||||
|
tr.addChild(name="candidate",attrs={ |
||||||
|
'cid':"jin_ft_cd_%d" % id, |
||||||
|
'host':host, |
||||||
|
'jid':mfrom, |
||||||
|
'port':port, |
||||||
|
'priority':priority, |
||||||
|
'type':'direct'}) |
||||||
|
return tr |
||||||
|
|
||||||
@ -0,0 +1,52 @@ |
|||||||
|
import socket, random |
||||||
|
|
||||||
|
def s5b_prepare(): |
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
||||||
|
|
||||||
|
port = None |
||||||
|
while True: |
||||||
|
port = random.randint(10000,2**16-1) |
||||||
|
try: |
||||||
|
s.bind(('', port)) |
||||||
|
s.listen(1) |
||||||
|
break |
||||||
|
except socket.error: |
||||||
|
pass |
||||||
|
|
||||||
|
return (s,port) |
||||||
|
|
||||||
|
def s5b_write_file(s,fd,size): |
||||||
|
s.settimeout(20) |
||||||
|
conn, addr = s.accept() |
||||||
|
data = conn.recv(3) |
||||||
|
|
||||||
|
assert data[0]=='\x05' #SOCKS version not 5 |
||||||
|
assert data[1]=='\x01' #not a connect command |
||||||
|
assert data[2]=='\x00' #does not support other connection method |
||||||
|
|
||||||
|
#send VER=5 METHOD=NO_AUTH |
||||||
|
conn.sendall('\x05\x00') |
||||||
|
|
||||||
|
data = conn.recv(47) |
||||||
|
|
||||||
|
assert data[0]=='\x05' # SOCKS version not 5 |
||||||
|
assert data[1]=='\x01' # not a connect command |
||||||
|
# data[2] is reserved |
||||||
|
assert data[3]=='\x03' # addr type is name |
||||||
|
assert data[4]=='(' |
||||||
|
name = data[5:45] |
||||||
|
assert data[45]=='\x00' |
||||||
|
assert data[46]=='\x00' |
||||||
|
|
||||||
|
#ACK |
||||||
|
conn.sendall('\x05\x00\x00'+'\x03('+name+'\x00\x00') |
||||||
|
#send file |
||||||
|
data = fd.read(min(size,1024)) |
||||||
|
size -= len(data) |
||||||
|
while data!='': |
||||||
|
conn.sendall(data) |
||||||
|
data = fd.read(min(size,1024)) |
||||||
|
size -= len(data) |
||||||
|
|
||||||
|
conn.close() |
||||||
|
fd.close() |
||||||
@ -0,0 +1,164 @@ |
|||||||
|
|
||||||
|
import xmpp, os, hashlib, time, brathuhn |
||||||
|
import socket, subprocess, random, s5b, util |
||||||
|
import config |
||||||
|
from threading import Thread |
||||||
|
from datetime import datetime |
||||||
|
|
||||||
|
GET_IP_CMD = ["dig", "myip.opendns.com", "@resolver1.opendns.com", "+short"] |
||||||
|
PROXY = config.S5B_PROXY |
||||||
|
|
||||||
|
ID=random.randint(0,1000000) |
||||||
|
|
||||||
|
BSTREAM_NS = "http://jabber.org/protocol/bytestreams" |
||||||
|
SI_NS = 'http://jabber.org/protocol/si' |
||||||
|
FILE_NS = 'http://jabber.org/protocol/si/profile/file-transfer' |
||||||
|
FEATURE_NS = 'http://jabber.org/protocol/feature-neg' |
||||||
|
X_DATA_NS = 'jabber:x:data' |
||||||
|
JABBER_NS = 'jabber:client' |
||||||
|
|
||||||
|
BYTESTREAM = 'http://jabber.org/protocol/bytestreams' |
||||||
|
IBB = 'http://jabber.org/protocol/ibb' |
||||||
|
|
||||||
|
transfer_ids = dict() |
||||||
|
queries = dict() |
||||||
|
|
||||||
|
LOCAL_IP = util.get_local_ip() |
||||||
|
|
||||||
|
def create_init_message(mfrom,to,name,size,fd): |
||||||
|
global ID |
||||||
|
global transfer_ids |
||||||
|
ID+=1 |
||||||
|
|
||||||
|
transfer_ids[unicode("si_%d"%ID)]=[fd,ID,size] |
||||||
|
|
||||||
|
iq=xmpp.Iq(xmlns=JABBER_NS, |
||||||
|
attrs={'from':unicode(mfrom),'to':to,'id':"si_%d" % ID,'type':'set'}) |
||||||
|
si=iq.addChild(name="si",namespace=SI_NS, attrs={'id':"si_%d" % ID, 'profile':FILE_NS}) |
||||||
|
si.addChild(name="file", namespace=FILE_NS, attrs={'name':name,'size':size}) |
||||||
|
fr=si.addChild(name="feature", namespace=FEATURE_NS) |
||||||
|
x=fr.addChild(name="x", namespace=X_DATA_NS, attrs={'type':'form'}) |
||||||
|
fd=x.addChild(name="field",attrs={'type':'list-single','var':'stream-method'}) |
||||||
|
|
||||||
|
opt=fd.addChild(name="option") |
||||||
|
val=opt.addChild(name="value") |
||||||
|
val.addData(BYTESTREAM) |
||||||
|
|
||||||
|
opt=fd.addChild(name="option") |
||||||
|
val=opt.addChild(name="value") |
||||||
|
val.addData(IBB) |
||||||
|
|
||||||
|
return iq |
||||||
|
|
||||||
|
def create_bytestream_query_message(mfrom,to,port,cid): |
||||||
|
global queries |
||||||
|
|
||||||
|
sid = "si_%d" % cid |
||||||
|
queries[sid] = cid |
||||||
|
|
||||||
|
iq=xmpp.Iq(xmlns=JABBER_NS, |
||||||
|
attrs={'from':unicode(mfrom),'to':to,'id':sid,'type':'set'}) |
||||||
|
|
||||||
|
q = iq.addChild(name="query",namespace=BSTREAM_NS, attrs={'sid':sid}) |
||||||
|
|
||||||
|
hosts = [] |
||||||
|
|
||||||
|
p=subprocess.Popen(GET_IP_CMD,stdout=subprocess.PIPE) |
||||||
|
p.wait() |
||||||
|
hosts.append(p.stdout.read()) |
||||||
|
hosts.append(LOCAL_IP) |
||||||
|
|
||||||
|
for host in hosts: |
||||||
|
q.addChild(name="streamhost",attrs={'jid':unicode(mfrom),'port':str(port),'host':host}) |
||||||
|
|
||||||
|
#print "<!--out-->\n",q |
||||||
|
return iq |
||||||
|
|
||||||
|
def start_ibb(cid,mfrom,fd): |
||||||
|
print "IBB" |
||||||
|
stream = xmpp.filetransfer.IBB() |
||||||
|
stream.PlugIn(brathuhn.cl) |
||||||
|
stream.OpenStream("si_%d" % cid, mfrom, fd, blocksize=4096) |
||||||
|
|
||||||
|
def ft_query(conn,msg): |
||||||
|
global queries |
||||||
|
global transfer_ids |
||||||
|
|
||||||
|
sid = msg.attrs['id'] |
||||||
|
cid = queries[sid] |
||||||
|
|
||||||
|
assert sid in transfer_ids |
||||||
|
|
||||||
|
fd = transfer_ids[ sid ][0] |
||||||
|
|
||||||
|
if msg.attrs['type']=='error': |
||||||
|
start_ibb(cid, unicode(msg.getFrom()), fd) |
||||||
|
del transfer_ids[ sid ] |
||||||
|
del queries[ sid ] |
||||||
|
|
||||||
|
def ft_init(conn,msg): |
||||||
|
global ID |
||||||
|
sid = msg.attrs['id'] |
||||||
|
if msg.attrs['type']=='result': |
||||||
|
fd = transfer_ids[ sid ][0] |
||||||
|
size = transfer_ids[ sid ][2] |
||||||
|
current_id = transfer_ids[ sid ][1] |
||||||
|
else: |
||||||
|
del transfer_ids[ sid ] |
||||||
|
return |
||||||
|
|
||||||
|
si=msg.getChildren()[0] |
||||||
|
# check if cancel message |
||||||
|
if si.name!='si': |
||||||
|
return |
||||||
|
|
||||||
|
fr=si.getChildren()[0] |
||||||
|
# some clients send a profile name |
||||||
|
# we will ignore it i.e take the next child |
||||||
|
if fr.name=='file': |
||||||
|
fr=si.getChildren()[1] |
||||||
|
if fr.name!='feature': |
||||||
|
return |
||||||
|
x=fr.getChildren()[0] |
||||||
|
if x.name!='x' and x.attrs['type']!='submit': |
||||||
|
return |
||||||
|
fi=x.getChildren()[0] |
||||||
|
if fi.name!='field': |
||||||
|
return |
||||||
|
val=fi.getChildren()[0] |
||||||
|
if val.name!='value': |
||||||
|
return |
||||||
|
|
||||||
|
if val.data[0]==BYTESTREAM: |
||||||
|
print "BYTESTREAM" |
||||||
|
|
||||||
|
s,port=s5b.s5b_prepare() |
||||||
|
|
||||||
|
q = create_bytestream_query_message(brathuhn.room_nick,msg.getFrom(),port,current_id) |
||||||
|
brathuhn.cl.send(q) |
||||||
|
|
||||||
|
def __run(): |
||||||
|
s5b.s5b_write_file(s,fd,size) |
||||||
|
Thread(target=__run()).start() |
||||||
|
|
||||||
|
ID += 1 |
||||||
|
|
||||||
|
elif val.data[0]==IBB: |
||||||
|
start_ibb(current_id, unicode(msg.getFrom()), fd) |
||||||
|
|
||||||
|
|
||||||
|
def ft_listener(conn,msg): |
||||||
|
global transfer_ids |
||||||
|
global queries |
||||||
|
|
||||||
|
assert msg.name=='iq' |
||||||
|
sid = msg.attrs['id'] |
||||||
|
if sid in transfer_ids and not sid in queries: |
||||||
|
print "init" |
||||||
|
ft_init(conn,msg) |
||||||
|
return |
||||||
|
if sid in queries: |
||||||
|
ft_query(conn,msg) |
||||||
|
return |
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,39 @@ |
|||||||
|
import select |
||||||
|
import socket |
||||||
|
import threading |
||||||
|
import random |
||||||
|
from Queue import Queue, Empty |
||||||
|
|
||||||
|
MAGIC_PACKET = "" |
||||||
|
for i in xrange(50): |
||||||
|
MAGIC_PACKET += chr(random.randrange(ord('a'),ord('z'))) |
||||||
|
|
||||||
|
def get_local_ip(): |
||||||
|
def udp_listening_server(): |
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
||||||
|
s.bind(('<broadcast>', 8888)) |
||||||
|
s.setblocking(0) |
||||||
|
while True: |
||||||
|
result = select.select([s],[],[]) |
||||||
|
msg, address = result[0][0].recvfrom(1024) |
||||||
|
msg = unicode(msg) |
||||||
|
if msg == MAGIC_PACKET: |
||||||
|
break |
||||||
|
queue.put(address) |
||||||
|
|
||||||
|
queue = Queue() |
||||||
|
thread = threading.Thread(target=udp_listening_server) |
||||||
|
thread.queue = queue |
||||||
|
thread.start() |
||||||
|
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
||||||
|
s2.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) |
||||||
|
waiting = True |
||||||
|
while waiting: |
||||||
|
s2.sendto(bytes(MAGIC_PACKET), ('<broadcast>', 8888)) |
||||||
|
try: |
||||||
|
address = queue.get(False) |
||||||
|
except Empty: |
||||||
|
pass |
||||||
|
else: |
||||||
|
waiting = False |
||||||
|
return address[0] |
||||||
Loading…
Reference in new issue