source: n4d/trunk/fuentes/install-files/usr/share/n4d/xmlrpc-server/core.py @ 3547

Last change on this file since 3547 was 3547, checked in by hectorgh, 3 years ago

VariablesManager? changes. Read changelog. startup thread is launched after service is up

File size: 32.3 KB
Line 
1# -*- coding: utf-8 -*-
2
3import syslog
4import os
5import os.path
6import imp
7import subprocess
8import unicodedata
9import xmlrpclib
10from ConfigurationManager import *
11from ClassPam import *
12import random
13import string
14import glib
15import time
16import threading
17import datetime
18import time
19import netifaces
20import traceback
21import grp
22import pwd
23import sys
24import tempfile
25
26
27threading._DummyThread._Thread__stop = lambda x: 42
28
29LOG_FILE="/var/log/n4d/error_log"
30SERVER_LOG="/var/log/n4d/n4d-server"
31CUSTOM_LOCAL_DISPATCH_DIR="/usr/share/n4d/xmlrpc-server/custom-local-dispatch/"
32N4D_ID=random.random()
33ONE_SHOT_LOG="/tmp/n4d-oneshot.log"
34N4D_TOKEN="/tmp/.n4d_pid"
35
36AUTHENTICATION_ERROR=0
37NOT_ALLOWED=1
38METHOD_NOT_FOUND=2
39CLASS_NOT_FOUND=2.1
40RUN=3
41UNSECURE_METHOD=4
42
43roottry = 0
44filerootpass = "/etc/n4d/key"
45
46CUSTOM_VARIABLES_PATH="/usr/share/n4d/xmlrpc-server/custom-variables/"
47POST_INIT_CUSTOM_VARIABLES_PATH="/usr/share/n4d/xmlrpc-server/post-init-custom-variables/"
48CUSTOM_DISPATCH_LOGIC="/usr/share/n4d/xmlrpc-server/custom-remote-dispatch-logic.py"
49
50
51configuration_path="/etc/n4d/conf.d"
52#class_skel="/usr/share/n4d/xmlrpc-server/class_skel.py"
53perl_class_skel="/usr/share/n4d/xmlrpc-server/perl_support/class_skel.skel"
54perl_function_skel="/usr/share/n4d/xmlrpc-server/perl_support/function_skel.skel"
55ONE_SHOT_PATH="/etc/n4d/one-shot/"
56
57objects={}
58
59
60
61class_skel="import subprocess\nclass %CLASSNAME%:\n"
62method_skel="\tdef %METHOD%(self,*params):\n\t\tpopen_list=[]\n\t\tpopen_list.append('%BINARY%')\n\t\tfor param in params:\n\t\t\tpopen_list.append(str(param))\n\t\tprint('[BINARY-PLUGIN] Before execution...')\n\t\toutput = subprocess.Popen(popen_list, stdout=subprocess.PIPE).communicate()[0]\n\t\tprint('[BINARY-PLUGIN] Execution returns ' + str(output))\n\t\treturn output\n\n"
63
64srv_logger=open(SERVER_LOG,"w")
65
66
67
68class n4dlog(object):
69       
70        def __init__(self,f):
71               
72                self.f=f
73       
74        def __get__(self,obj,type=None):
75               
76                return self.__class__(self.f.__get__(obj,type))
77
78        def __call__(self,*args,**kw):
79               
80                try:
81                        return self.f(*args,**kw)
82                except Exception as e:
83                        mode="w"
84                        if os.path.exists(LOG_FILE):
85                                mode="a"
86                               
87                        f=open(LOG_FILE,mode)
88                        f.write("\n")
89                        f.write(traceback.format_exc())
90                        f.close()
91                        raise e
92                       
93                               
94               
95#def call
96       
97#class n4dlog
98
99class ServiceManager:
100       
101        path="/etc/n4d/controlled-startups.d/"
102
103        def __init__(self):
104               
105                self.enabled_services=[]
106                self.get_list()
107               
108               
109        def get_list(self):
110                self.enabled_services=[]
111                for item in os.listdir(ServiceManager.path):
112                        if os.path.isfile(ServiceManager.path+item):
113                                self.enabled_services.append(item)
114               
115        #def init
116       
117       
118#class ServiceManager
119       
120
121       
122class SystemProcess:
123       
124        def __init__(self):
125               
126                self.process_list=[]
127                self.get_process_list()
128
129        #def init
130       
131        def get_process_list(self):
132               
133                self.process_list=[]
134               
135                p=subprocess.Popen(["ps","aux"],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
136                output=p.communicate()[0]
137                lst=output.split("\n")
138                lst.pop(0)
139               
140                for item in lst:
141                        processed_line=item.split(" ")
142                        tmp_list=[]
143                       
144                        if len(processed_line) >= 10:
145                                for object in processed_line:
146                                        if object!="":
147                                                tmp_list.append(object)
148                                processed_line=tmp_list
149                               
150                                process={}
151                                process["user"]=processed_line[0]
152                                process["pid"]=processed_line[1]
153                                process["cpu"]=processed_line[2]
154                                process["mem"]=processed_line[3]
155                                process["vsz"]=processed_line[4]
156                                process["rss"]=processed_line[5]
157                                process["tty"]=processed_line[6]
158                                process["stat"]=processed_line[7]
159                                process["start"]=processed_line[8]
160                                process["time"]=processed_line[9]
161                                cmd=""
162                                for line in processed_line[10:]:
163                                        if cmd!="":
164                                                cmd+=" "
165                                        cmd+=line
166                                       
167                                process["command"]=cmd.split(" ")[0]
168                                self.process_list.append(process)
169               
170        #def get_process_list
171       
172       
173        def get_user_process_list(self,user):
174               
175                ret_list=[]
176               
177                for process in self.process_list:
178                        if process["user"]==user:
179                                ret_list.append(process)
180                               
181                return ret_list
182               
183        #def get_user_process_list
184       
185        def find_process(self,filter):
186                self.get_process_list()
187                ret_list=[]
188                for process in self.process_list:
189                        if filter in process["command"]:
190                                ret_list.append(process)
191                               
192                               
193                if len(ret_list)>0:
194                        return ret_list
195                else:
196                        return None
197               
198        #def find_process
199       
200       
201#class SystemProcess
202
203
204srv_logger.write("\n[CORE] Starting N4D ...\n")
205print("\n[CORE] Starting N4D ...")
206
207f = open(filerootpass)
208master_password = f.readline().strip('\n')
209f.close()
210
211
212
213def clear_credentials():
214       
215        print "Clearing credentials..."
216        credentials={}
217        return True
218       
219#def clear_credentials
220
221
222def generate_rootpasswd():
223        f = open(filerootpass,'w')
224        generatepassword ="".join(random.sample(string.letters+string.digits, 50))
225        f.write(generatepassword+"\n")
226        f.close()
227        prevmask = os.umask(0)
228        os.chmod(filerootpass,0400)
229        os.chown(filerootpass,0,0)
230        os.umask(prevmask)
231        readpass = generatepassword
232        return readpass
233
234
235
236# ONE SHOTS
237
238def one_shot():
239       
240        cs=SystemProcess()
241
242        one_shot_list=os.listdir(ONE_SHOT_PATH)
243
244        wait=True
245
246        if len(one_shot_list)>0:
247
248                print("[ONE-SHOT] Executing one-shots...")
249
250                while(wait):
251                        processes=cs.find_process("dpkg")
252                        if processes==None:
253                                wait=False
254
255                        time.sleep(2)
256                       
257                if len(one_shot_list) > 0:
258                        f=open(ONE_SHOT_LOG,"w")
259                for item in one_shot_list:
260                        print("\t" + str(item) + "...")
261                        '''
262                        p=subprocess.Popen(ONE_SHOT_PATH+item)
263                        p.wait()
264                        '''
265                        ret=os.system(ONE_SHOT_PATH+item)
266                        if ret==0:
267                                f.write(item +" OK\n")
268                        else:
269                                f.write(item +" FAILED WITH EXIT STATUS " + str(ret) + "\n")
270                        try:
271                                os.remove(ONE_SHOT_PATH+item)
272                        except:
273                                pass
274                       
275
276n4d_core_one_shot_t=threading.Thread(target=one_shot)
277n4d_core_one_shot_t.daemon=True
278# Will be executed in server.py after socket is ready
279#n4d_core_one_shot_t.start()
280
281
282# CUSTOM VARIABLES
283
284srv_logger.write("[CORE] Loading custom variables ... \n")
285print("[CORE] Loading custom variables ... ")
286flist=os.listdir(CUSTOM_VARIABLES_PATH)
287
288for file in flist:
289        if file.endswith(".py"):
290                path=CUSTOM_VARIABLES_PATH+file
291                srv_logger.write("\t " + path + " ... ")               
292                sys.stdout.write("\t " + path + " ... ")
293                try:
294                        execfile(path)
295                        srv_logger.write("OK\n")               
296                        print("OK")
297                except Exception as e:
298                        print("FAILED")
299                        srv_logger.write("FAILED\n")
300                        sys.stdout.write("\t\t[!] ")
301                        srv_logger.write("\t\t[!] " + str(e) + "\n")           
302                        print(e)
303                       
304       
305
306# IMPORTING CLASSES
307
308cm=ConfigurationManager(configuration_path)
309remotefunctions = []
310
311def load_plugin(plugin):
312       
313        global class_skel
314        global method_skel
315        global objects
316       
317        if os.path.exists(plugin.path):
318       
319                if plugin.class_name!="VariablesManager":
320                        try:
321                                srv_logger.write( "\t["+plugin.class_name+"] " + plugin.path + " ... " )
322                        except:
323                                pass
324                        sys.stdout.write( "\t["+plugin.class_name+"] " + plugin.path + " ... " )
325                else:
326                        try:
327                                srv_logger.write( "\t["+plugin.class_name+"] " + plugin.path + " ... \n" )
328                        except:
329                                pass
330                        print( "\t["+plugin.class_name+"] " + plugin.path + " ... " )
331               
332                if plugin.type=="python" and plugin.path!=None:
333                        try:
334                               
335                                execfile(plugin.path,globals())
336                                s=globals()[plugin.class_name]()
337                                objects[plugin.class_name]=s
338                                if plugin.class_name!="VariablesManager":
339                                        try:
340                                                srv_logger.write("OK\n")
341                                        except:
342                                                pass
343                                        print("OK")
344                        except Exception as e:
345                                print e
346                                try:
347                                        srv_logger.write("FAILED\n")
348                                        srv_logger.write("\t\t[!] " + str(e) + "\n")
349                                except:
350                                        pass
351                                print("FAILED")
352                               
353                                sys.stdout.write("\t\t[!] ")
354                                print(e)
355                               
356
357                if plugin.type=="binary" and plugin.path!=None and os.path.exists(plugin.path):
358                       
359                       
360                        code=class_skel
361                        code=code.replace("%CLASSNAME%",plugin.class_name)
362                       
363                       
364                        for method in plugin.function:
365                               
366                                tmp=method_skel
367                                if len(plugin.function)>=1 and plugin.standalone==False:
368                                        tmp=tmp.replace("popen_list.append('%BINARY%')","popen_list.append('%BINARY%')\n\t\tpopen_list.append('%METHOD%')")
369                                tmp=tmp.replace("%METHOD%",method)
370                                tmp=tmp.replace("%METHOD%",plugin.bin_name)
371                                tmp=tmp.replace("%BINARY%",plugin.path)
372                                       
373                                code+=tmp               
374                       
375                        #print code
376                        try:
377                                exec(code,globals())
378                                s=globals()[plugin.class_name]()
379                                objects[plugin.class_name]=s
380                                try:
381                                        srv_logger.write("OK\n")
382                                except:
383                                        pass
384                                print("OK")
385                        except Exception as e:
386                                try:
387                                        srv_logger.write("FAILED\n")
388                                        srv_logger.write("\t\t[!] " + str(e) + "\n")
389                                except:
390                                        pass
391                                print("FAILED")
392                               
393                                sys.stdout.write("\t\t[!] ")
394                                print(e)
395                       
396
397                if plugin.type=="perl" and plugin.path!=None and os.path.exists(plugin.path):
398                        cf = open(perl_class_skel,'r')
399                        ff = open(perl_function_skel,'r')
400                        lines = cf.readlines()
401                        code = "".join(lines)
402                        code = code.replace("%CLASSNAME%",plugin.class_name)
403                        cf.close()
404                        lines = ff.readlines()
405                        function_template = "".join(lines)
406                        ff.close()
407                        for aux_func in plugin.function.keys():
408                                a = function_template
409                                a = a.replace("%CLASSNAME%",plugin.class_name)
410                                a = a.replace("%METHOD%",aux_func)
411                                code += a
412                        try:
413                                exec(code,globals())
414                                s=globals()[plugin.class_name]()
415                                objects[plugin.class_name]=s
416                        except Exception as e:
417                                try:
418                                        srv_logger.write("FAILED\n")
419                                        srv_logger.write("\t\t[!] " + str(e) + "\n")           
420                                except:
421                                        pass
422                                print("FAILED")
423                                sys.stdout.write("\t\t[!] ")
424                                print(e)
425
426                if plugin.type=="remote":
427                        server = {}
428                        server["ip"] = plugin.remoteip
429                        server["order"] = int(plugin.order)
430                        server["function"] = plugin.functionremote
431                        remotefunctions.append(server) 
432       
433       
434#def load_plugin
435               
436
437# CUSTOM VARIABLES
438
439print("[CORE] Loading post init custom variables ... ")
440srv_logger.write("[CORE] Loading post init custom variables ... \n")           
441flist=os.listdir(POST_INIT_CUSTOM_VARIABLES_PATH)
442
443for file in flist:
444        if file.endswith(".py"):
445                path=POST_INIT_CUSTOM_VARIABLES_PATH+file
446                srv_logger.write("\t " + path + " ... ")
447                sys.stdout.write("\t " + path + " ... ")
448                try:
449                        execfile(path)
450                       
451                        srv_logger.write("OK\n")
452                        print("OK")
453                except Exception as e:
454                        srv_logger.write("FAILED\n")
455                        srv_logger.write("\t\t[!] " + str(e) + "\n")           
456                        print("FAILED")
457                        sys.stdout("\t\t[!] ")
458                        print(e)
459                       
460
461def load_external_module(code,plugin_conf):
462        global cm
463        global objects
464        try:
465                exec(code)
466                s=locals()[plugin_conf.class_name]()
467                objects[plugin_conf.class_name]=s
468                cm.plugins.append(plugin_conf)
469                return (True,)
470        except Exception as e:
471                return (False,e)
472       
473
474def load_module_by_conf_file(etc_file):
475       
476        global cm
477        global objects
478        print ("[CORE] Loading module by conf file " + etc_file + " ...")
479        try:
480                plugin=cm.load_plugin(etc_file)
481                if plugin!=None:
482                        load_plugin(plugin)
483                        count=0
484                        for item in cm.plugins:
485                                if item.class_name==plugin.class_name:
486                                        cm.plugins.pop(count)
487                                        break
488                                count+=1
489                        cm.plugins.append(plugin)
490                       
491                        global executed_objects
492                       
493                        count=0
494                        for item in executed_objects:
495                                if item==plugin.class_name:
496                                        executed_objects.pop(count)
497                                        break
498                                count+=1
499
500                        load_t=threading.Thread(target=startup_launcher,args=(objects,))
501                        load_t.daemon=True
502                        load_t.start()
503                        #startup_launcher(objects)
504                       
505                        return (True,True)
506        except Exception as e:
507                print(e)
508                return (False,e)
509       
510#load_module_by_file
511
512def load_new_modules(path=configuration_path):
513       
514        global cm
515        global objects
516       
517        file_list=os.listdir(path)
518        print("[CORE] Loading new modules...")
519        for file in file_list:
520                file_path=path+"/"+file
521                try:
522                        plugin=cm.load_plugin(file_path)
523                except:
524                        plugin=None
525
526                if plugin!=None:
527                        if plugin.class_name not in objects:
528                                try:
529                                        print("\t[*] Loading " + plugin.class_name +" ...")
530                                        load_plugin(plugin)
531                                        cm.plugins.append(plugin)
532                                        #return (True,plugin.class_name)
533                                except Exception as e:
534                                        print(e)
535                                        #return(False,e)
536                        else:
537                                print("\t[!] " + plugin.class_name + " already loaded. Skipping...")
538                               
539       
540        return True
541       
542       
543#def load_new_modules
544
545def unload_module(conf_file):
546
547        global cm
548        global objects
549        plugin=cm.load_plugin(conf_file)
550
551        if plugin==None:
552                print("[CORE] Unable to unload " + conf_file)
553                return "Unable to load " + conf_file
554       
555        count=0
556        for item in cm.plugins:
557                if plugin.class_name==item.class_name:
558                        cm.plugins.pop(count)
559                       
560                        break
561                count+=1
562       
563        objects.pop(plugin.class_name)
564        print("[CORE] Removing " + plugin.class_name + " ...")
565        return True
566       
567       
568       
569#def unload_module
570
571
572# installed plugins loading
573srv_logger.write("[CORE] Loading installed plugins...\n")
574print("[CORE] Loading installed plugins...")
575for plugin in cm.plugins:
576        load_plugin(plugin)
577       
578#
579
580
581sm=ServiceManager()
582
583# STARTUP
584
585N4DLOGSTARTUP = '/var/log/n4d/startup'
586
587executed_objects = []
588
589def startup_launcher(objects_list):
590        print("[CORE] Executing startups ... ")
591        global executed_objects
592        global sm
593        withstartup = []
594        next_objects = []
595        filelog = open(N4DLOGSTARTUP,'a')
596        sm.get_list()
597        for x in objects_list.keys():
598                try:
599                        if x in executed_objects:
600                                continue
601                        callable(getattr(objects_list[x],'startup'))
602                        options={}
603                        # FILTER CODE GOES HERE
604                        if x in sm.enabled_services:
605                                options["controlled"]=True
606                        else:
607                                options["controlled"]=False
608                        #
609                       
610                        #FIRST BOOT CODE GOES HERE
611                        options["boot"]=False
612                        if not os.path.exists(N4D_TOKEN):
613                                options["boot"]=True
614                               
615                        withstartup.append((objects_list[x],options))
616                       
617                except Exception as e:
618                        pass
619        change = True
620        while change:
621                change = False
622                for x in range(len(withstartup)-1,-1,-1):
623                        if ( not hasattr(withstartup[x][0],'predepends') or len( set(withstartup[x][0].predepends) - set(executed_objects)) <= 0 ) \
624                        and ( not hasattr(withstartup[x][0],'next_to') or len( set(withstartup[x][0].next_to) - set(next_objects)) <= 0):
625                                try:
626                                        print("\t[STARTUP] Executing " +  withstartup[x][0].__class__.__name__ + " with options " +  str(withstartup[x][1]) + " ...")
627                                        withstartup[x][0].startup(withstartup[x][1])
628                                        executed_objects.append(withstartup[x][0].__class__.__name__)
629                                except Exception as e:
630                                        filelog.write( "[ "+datetime.datetime.today().strftime("%d/%m/%y %H:%M:%S") + " ] Class " + withstartup[x][0].__class__.__name__ + " had an error on startup method because " + str(e) + "\n")
631                                next_objects.append(withstartup[x][0].__class__.__name__)
632                                withstartup.pop(x)
633                                change = True
634        for x in withstartup:
635                filelog.write("[ "+datetime.datetime.today().strftime("%d/%m/%y %H:%M:%S") + " ] Class " +x.__class__.__name__+" can't be executed. Check if depends exists or had an error when launching startup method\n")
636        filelog.close()
637
638        f=open(N4D_TOKEN,"w")
639        f.write(str(os.getpid()))
640        f.close()
641
642       
643       
644#def startup_launcher
645
646
647
648
649n4d_core_startup_t=threading.Thread(target=startup_launcher,args=(objects,))
650n4d_core_startup_t.daemon=True
651# Will be executed in server.py after socket is ready
652#n4d_core_startup_t.start()
653
654
655#  APT LAUNCHER
656
657N4DLOGAPT='/var/log/n4d/apt'
658
659def apt_launcher():
660        global sm
661        sm.get_list()
662        f=open(N4DLOGAPT,"a")
663        f.write("["+datetime.datetime.today().strftime("%d/%m/%y %H:%M:%S")+"] Executing n4d-apt...\n")
664        for plugin in sorted(objects.keys()):
665       
666                try:
667                        if hasattr(objects[plugin],"apt") and callable(getattr(objects[plugin],"apt")) and plugin not in sm.enabled_services:
668                                f.write("["+datetime.datetime.today().strftime("%d/%m/%y %H:%M:%S") + "] Executing " + objects[plugin].__class__.__name__ + " ...\t")
669                                objects[plugin].apt()
670                                f.write("OK\n")
671                except:
672                        f.write("FAILED [!]\n")
673                       
674        f.write("["+datetime.datetime.today().strftime("%d/%m/%y %H:%M:%S") + "] n4d-apt done\n")
675        f.close()
676       
677        return True
678       
679#def apt_launcher
680
681
682
683
684
685def n4d_cron():
686
687        cron_resolution=5
688        sleep_time=60*cron_resolution
689
690        minutes=0
691       
692        while True:
693                               
694                time.sleep(sleep_time)
695                minutes+=cron_resolution
696                for plugin in sorted(objects.keys()):
697                       
698                        #print dir(objects[plugin])
699                        try:
700                                if hasattr(objects[plugin],"n4d_cron") and callable(getattr(objects[plugin],"n4d_cron")):
701                                        print ("[N4DCRON] Executing " + objects[plugin].__class__.__name__ + " cron after %i minutes...\t"%minutes)
702                                        objects[plugin].n4d_cron(minutes)
703                        except Exception as e:
704                                print(e)
705
706
707n4d_cron_thread=threading.Thread(target=n4d_cron)
708n4d_cron_thread.daemon=True
709# Will be executed in server.py after socket is ready
710#n4d_cron_thread.start()
711       
712# OLD FUNCTION LIST
713
714teachers_func_list=[]
715students_func_list=[]
716admin_func_list=[]
717others_func_list=[]
718
719for plugin in cm.plugins:
720        for func in plugin.function:
721                       
722                if "teachers" in plugin.function[func]:
723                        teachers_func_list.append(func)
724                       
725                if "students" in plugin.function[func]:
726                        students_func_list.append(func)
727                       
728                if "admin" in plugin.function[func]:
729                        admin_func_list.append(func)
730                       
731                if "others" in plugin.function[func]:
732                        others_func_list.append(func)
733
734
735
736
737def get_methods(params):
738       
739        ret=""
740        filter_class = []
741        if len(params) > 0 :
742                filter_class = params[0]
743               
744        processed=[]
745        for i in range(len(cm.plugins)-1,-1,-1):
746                plugin=cm.plugins[i]
747                if plugin.class_name not in processed:
748                        processed.append(plugin.class_name)
749                        for method in plugin.function:
750                                groups=""
751                                for group in plugin.function[method]:
752                                        groups+=group + " "
753                                if len(filter_class) == 0 or plugin.class_name in filter_class: 
754                                        ret+="[" + plugin.class_name + "] " + method + " : " + groups + "\n"
755                        if plugin.type=="remote":
756                                for method in plugin.functionremote:
757                                        if len(filter_class) == 0 or plugin.class_name in filter_class :
758                                                ret+="(r:" + plugin.remoteip + ")["+ method[1:method.find(")")]+"] " + method[method.find(")")+1:] + "\n"
759        return ret     
760       
761#def get_methods
762
763
764def get_sorted_methods():
765       
766        ret={}
767       
768        for plugin in cm.plugins:
769                methods=[]
770                for method in plugin.function:
771                        methods.append(method)
772                ret[plugin.class_name]=methods
773               
774        return ret
775       
776       
777#def get_sorted_methods
778
779
780n4d_id_list={}
781
782def get_next_n4d_id():
783       
784        sorted_list=sorted(n4d_id_list)
785        try:
786                last=sorted_list[len(n4d_id_list)-1]
787                last+=1
788        except:
789                last=0
790               
791        return last
792       
793#def get_next_n4d_id
794
795def add_n4d_id(function,user,password):
796       
797        dic={}
798        dic["method"]=function
799        dic["user"]=user
800        dic["password"]=password
801       
802        id=get_next_n4d_id()
803        n4d_id_list[id]=dic
804       
805        return id
806       
807#def add n4d id
808
809
810def get_ip(dev):
811        '''
812        Returns ip value from a certain network interface. It returns None on failure.
813        ex:
814                get_ip("eth0")
815        '''     
816        try:
817                info=get_device_info(dev)
818                return info["ip"]
819        except Exception as e:
820                print e
821                return None
822       
823#def get_ip
824
825
826
827def get_net_size(netmask):
828        '''
829        Calculates bitmask from netmask
830        ex:
831                get_broadcast("eth0")
832        '''
833        netmask=netmask.split(".")
834        binary_str = ''
835        for octet in netmask:
836                binary_str += bin(int(octet))[2:].zfill(8)
837        return str(len(binary_str.rstrip('0')))
838
839#def get_net_size
840
841def get_device_info(dev):
842        '''
843        Returns a dictionary with the information of a certain network interface.
844        ex:
845                get_device_info("eth0")
846        '''     
847        dic={}
848        for item in netifaces.interfaces():
849                if item==dev:
850                        info=netifaces.ifaddresses(item)
851                        dic["name"]=item
852                        if info.has_key(netifaces.AF_LINK):
853                                if info[netifaces.AF_LINK][0].has_key("addr"):
854                                        dic["mac"]=info[netifaces.AF_LINK][0]["addr"]
855                                else:
856                                        dic["mac"]=""
857                        if info.has_key(netifaces.AF_INET):
858                                if info[netifaces.AF_INET][0].has_key("broadcast"):
859                                        dic["broadcast"]=info[netifaces.AF_INET][0]["broadcast"]
860                                else:
861                                        dic["broadcast"]=""
862                                if info[netifaces.AF_INET][0].has_key("netmask"):
863                                        dic["netmask"]=info[netifaces.AF_INET][0]["netmask"]
864                                        dic["bitmask"]=get_net_size(dic["netmask"])
865                                else:
866                                        dic["bitmask"]=""
867                                        dic["netmask"]=""
868                                if info[netifaces.AF_INET][0].has_key("addr"):
869                                        dic["ip"]=info[netifaces.AF_INET][0]["addr"]
870                                else:
871                                        dic["ip"]=""
872                       
873        return dic
874       
875#def get_device_info
876
877def get_all_ips():
878       
879        ret=set()
880        ret.add("127.0.0.1")
881        for item in netifaces.interfaces():
882               
883                        ret.add(get_device_info(item)["ip"])
884               
885        return list(ret)
886       
887#def get_all_ips
888
889
890
891VALIDATE_TRIES={}
892
893def validate_user(user,password):
894       
895        global VALIDATE_TRIES
896        sleep_time=2
897       
898        pv= PamValidate()
899        if pv.authentication(user,password):
900               
901                groups = [g.gr_name for g in grp.getgrall() if user in g.gr_mem]
902                gid = pwd.getpwnam(user).pw_gid
903                groups.append(grp.getgrgid(gid).gr_name)               
904               
905                if user in VALIDATE_TRIES:
906                        VALIDATE_TRIES[user]=0
907                       
908                return (True,groups)
909        else:
910                if user not in VALIDATE_TRIES:
911                        VALIDATE_TRIES[user]=0
912                VALIDATE_TRIES[user]+=1
913                if VALIDATE_TRIES[user] > 10:
914                        print "[CORE][validate_user] Too many unsuccessful tries for user %s. Sleeping response..."%user
915                        time.sleep(VALIDATE_TRIES[user]*sleep_time)
916                       
917                return (False,[])
918       
919#def validate_user
920
921def exec_threads():
922       
923        global n4d_core_startup_t, n4d_core_one_shot_t,n4d_cron_thread
924
925        n4d_core_one_shot_t.start()
926        n4d_core_startup_t.start()
927        n4d_cron_thread.start()
928       
929#def exec_threads
930
931
932srv_logger.close()
933
934class Core:
935        '''N4D Core''' 
936       
937        debug=True
938        roottry=0
939
940        skynet="https://anubis:9779"
941        learn=False
942        store_lessons=False
943       
944
945        if os.path.exists(CUSTOM_DISPATCH_LOGIC):
946                execfile(CUSTOM_DISPATCH_LOGIC)
947        else:
948                def custom_remote_dispatch_logic(self):
949                        return True
950
951        def __init__(self):
952
953                global master_password
954                global objects
955                global cm
956                self.cm=cm
957                self.objects=objects
958                self.master_password=master_password
959                self.credentials={}
960                self.run=True
961                import threading
962                n4d_core_clear_t=threading.Thread(target=self.clear_credentials,args=())
963                n4d_core_clear_t.daemon=True
964                n4d_core_clear_t.start()
965               
966        def launch_triggers(self):
967               
968                for item in self.objects:
969                        print self.objects[item]
970               
971        #def launch_triggers
972               
973        def init_daemon(self):
974               
975                glib.timeout_add(5000,self.clear_credentials)
976                import gobject
977                gtk.main()
978       
979               
980        def clear_credentials(self):
981                while True:
982                        time.sleep(10)
983                self.grace_time=0
984                while True:
985                        time.sleep(self.grace_time)
986                        print "[CREDENTIALS CACHE] CLEARING CACHE"
987                        self.credentials={}
988                        self.grace_time=0
989                       
990                        time.sleep(200)
991
992
993        def dprint(self,data):
994                if Core.debug:
995                        print data
996                        sys.stdout.flush()
997                       
998        def get_all_ips(self):
999                return get_all_ips()
1000               
1001       
1002        @n4dlog
1003        def _dispatch(self,method,params):
1004
1005                global sm
1006
1007                client_address=params[0]
1008                params=params[1:]
1009               
1010                if method=="register_n4d_ticket":
1011
1012                        if "NTicketsManager" in objects:
1013                                try:
1014                                        usr=params[0]
1015                                        passwd=params[1]
1016                                        aux = PamValidate()
1017                                       
1018                                        if aux.authentication(usr,passwd):
1019                                                ticket=objects["NTicketsManager"].get_ticket(usr)       
1020                                                return ticket
1021                                except Exception as e:
1022                                        print e
1023                                        return False
1024                                       
1025                        return False
1026               
1027                if method=="register_credentials":
1028
1029                        print "registering credentials..."
1030
1031                        if client_address in get_all_ips():
1032                                #home
1033                                try:
1034                                        if len(params)==2:
1035                                                if params[0]==self.master_password:
1036                                                        try:
1037                                                                tmp_user,tmp_pass=params[1]
1038                                                        except:
1039                                                                return(False,"Second parameter must be a tuple containing user and password")
1040                                                               
1041                                                        self.credentials[tmp_user]=tmp_pass
1042                                                        self.grace_time=60
1043                                                        return(True,"Credentials registered")
1044                                                       
1045                                                       
1046                                                else:
1047                                                        return(False,"Key authentication error")
1048                                        else:
1049                                                return(False,"Invalid arguments for register_credentials(n4d_key,(user,password))")
1050                                               
1051                                except Exception as e:
1052                                        return (False,str(e))
1053                        else:
1054                                #away
1055                                print("client is not at home")
1056                                '''
1057                                try:
1058                                        if type(params[0])==type(("","")):
1059                                                tmp_user,tmp_pass=params[0]
1060                                                aux = PamValidate()
1061                                                if aux.authentication(tmp_user,tmp_pass):
1062                                                        self.credentials[tmp_user]=tmp_pass
1063                                                        self.grace_time=60
1064                                                        return(True,"Credentials registered")
1065                                                else:
1066                                                       
1067                                                       
1068                                        else:
1069                                                return(False,"First parameter must be a tuple containing user and password")
1070                                               
1071                                except Exception as e:
1072                                        return(False,str(e))
1073                                '''
1074                                return(False,"Function not supported remotely")
1075               
1076                if method=="get_methods":
1077                        return get_methods(params)
1078                if method=="get_sorted_methods":
1079                        try:
1080                                return get_sorted_methods()
1081                        except Exception as e:
1082                                print e
1083                                return "ERROR CONNECTING TO SKYNET"
1084                               
1085                if method=="get_n4d_id":
1086                        return str(N4D_ID)
1087                       
1088                if method=="get_ip":
1089                        try:
1090                                ret=get_ip(params[0])
1091                        except:
1092                                ret=""
1093                        return ret
1094               
1095                if method=="apt":
1096                        if params[0]==self.master_password:
1097                                return (True,apt_launcher())
1098                        else:
1099                                return (False,"AUTHENTICATION ERROR")
1100               
1101                if method=="load_module":
1102                        if params[0]==self.master_password:
1103                                try:
1104                                        return load_module_by_conf_file(params[1])
1105                                except Exception as e:
1106                                        return (False,e)
1107                                       
1108                        else:
1109                                return (False,"AUTHENTICATION ERROR")
1110                                       
1111                if method=="load_new_modules":
1112                        if params[0]==self.master_password:
1113                                try:
1114                                        if len(params)==1:
1115                                                return (True,load_new_modules())
1116                                        if len(params)>1:
1117                                                if type(params[1])==type(""):
1118                                                        return (True,load_new_modules(params[1]))
1119                                                else:
1120                                                        return (False,"Second parameter must be a system path")
1121                                except Exception as e:
1122                                        return (False,e)
1123                        else:
1124                                return (False,"AUTHENTICATION ERROR")
1125                                       
1126                if method=="unload_module":
1127
1128                        if params[0]==self.master_password:
1129                                try:
1130                                        if len(params)>1:
1131                                                if type(params[1])==type(""):
1132                                                        return (True,unload_module(params[1]))
1133                                                else:
1134                                                        return (False,"Second parameter must be a system path")
1135                                except Exception as e:
1136                                        return (False,e)
1137                        else:
1138                                return (False,"AUTHENTICATION ERROR")
1139                               
1140                if method=="get_service_list":
1141                       
1142                        ret={}
1143                        sm.get_list()
1144                        ret["enabled"]=sm.enabled_services
1145                        ret["disabled"]=[]
1146                        for item in objects:
1147                                if item not in sm.enabled_services:
1148                                        ret["disabled"].append(item)
1149                                       
1150                        return ret
1151                       
1152                if method=="is_controlled_startup":
1153                        try:
1154                               
1155                                ret={}
1156                                sm.get_list()
1157                                ret["enabled"]=sm.enabled_services
1158
1159                                if params[0] not in ret["enabled"]:
1160                                        return False
1161                                else:
1162                                        return True
1163                        except:
1164                                return False
1165
1166                               
1167                       
1168                if method=="validate_user":
1169                        try:
1170                                return validate_user(params[0],params[1])
1171                        except Exception as e:
1172                                print(e)
1173                                return False
1174                               
1175
1176                user=None
1177               
1178                try:
1179                        user,password,remote_user,remote_password=params[0]
1180                except:
1181                        try:
1182                                user,password=params[0]
1183                                remote_user=user
1184                                remote_password=password
1185
1186                        except:
1187                                try:
1188                                        if params[0] == "":
1189                                                user="anonymous"
1190                                                password=""
1191                                        else:
1192                                                user="root"
1193                                                password=params[0]
1194                                        remote_user=user
1195                       
1196                                        remote_password=params[0]
1197                                except Exception as e:
1198                                        return "FUNCTION NOT SUPPORTED"
1199                try:
1200                        class_name=params[1]
1201                        new_params=params[2:]
1202                except:
1203                        return "FUNCTION NOT SUPPORTED"
1204
1205               
1206                ret=self.custom_remote_dispatch_logic()
1207               
1208
1209                if ret:
1210                        order = -1
1211                        found = False
1212                        remoteip = ""
1213                        for x in remotefunctions:
1214                                if "("+class_name+")"+method in x["function"]:
1215                                        if order < x["order"]:
1216                                                order = x["order"]
1217                                                remoteip = x["ip"]
1218                                                found = True
1219                                               
1220                        if found:
1221                                try:
1222                                        server = xmlrpclib.ServerProxy("https://"+remoteip+":9779")
1223                                        remote_params=[]
1224                                        if user == "anonymous":
1225                                                remote_params.append("")
1226                                        elif user == "":
1227                                                remote_params.append(password)
1228                                        else:
1229                                                remote_params.append((remote_user,remote_password))                                     
1230                                        remote_params.append(class_name)
1231                                        for param in new_params:
1232                                                remote_params.append(param)
1233                                        add_n4d_id(method,user,password)
1234                                        return getattr(server,method)(*remote_params)
1235                                except:
1236                                        return "false :error connecting to server"     
1237
1238
1239               
1240                self.dprint("")
1241                self.dprint("[" + user + "@"+client_address+"] " + "Execution of method [" + method + "] from class " + class_name)
1242                #self.dprint("")
1243
1244                ret=self.validate_function(params[0],class_name,method,new_params,client_address)
1245
1246                try:
1247                        ret,new_params=ret
1248                except:
1249                        pass
1250
1251
1252                if ret ==RUN:
1253                       
1254                        add_n4d_id(method,user,password)
1255                        try:
1256                                ret=getattr(objects[class_name],method)(*new_params)
1257                                return ret
1258                        except Exception as e:
1259                                return {"status":False,"msg":"Exception captured by core: " + str(e),"function":method,"class_name":class_name,"parameters":new_params}
1260                       
1261                if ret==METHOD_NOT_FOUND:
1262                       
1263                        return "FUNCTION NOT SUPPORTED"
1264                       
1265                if ret==AUTHENTICATION_ERROR:
1266                        list_users = []
1267                        for x in pwd.getpwall():
1268                                if x.pw_uid >= 1000 :
1269                                        list_users.append(x[0])
1270                        if user in list_users:
1271                                return "USER AND/OR PASSWORD ERROR"
1272                        return "USER DOES NOT EXIST"
1273                       
1274                if ret==NOT_ALLOWED:
1275                       
1276                        return "METHOD NOT ALLOWED FOR YOUR GROUPS"
1277                       
1278                if ret==UNSECURE_METHOD:
1279                       
1280                        return "METHOD IS BEING CALLED IN AN UNSECURED WAY. USER PARAMETER MUST MATCH USER CLIENT INFO"
1281                       
1282                if ret==CLASS_NOT_FOUND:
1283                       
1284                        return "CLASS NOT FOUND"
1285       
1286        #def dispatch
1287
1288       
1289       
1290        def validate_function(self,user_password,class_name,method,new_params,client_address=None):
1291                userandpassword = True
1292                validate=True
1293                user_found=False
1294                try:
1295                        user,password = user_password
1296                       
1297                except:
1298
1299                        if user_password!="":
1300                                password = user_password
1301                                user="root"
1302                               
1303                                if password == self.master_password:
1304                                        user_found=True
1305                                        validate=False
1306                                        grouplist=["root"]
1307                                       
1308                                        '''
1309                                        if class_name in objects:
1310                                                for plugin in cm.plugins:
1311                                                        if plugin.class_name==class_name:
1312                                                                if method in plugin.function:
1313                                                                        user_found=True
1314                                                       
1315                                                return METHOD_NOT_FOUND
1316                                               
1317                                        else:
1318                                                return CLASS_NOT_FOUND
1319                                        '''
1320
1321                                else:
1322                                        user_found=False
1323                                        Core.roottry += 1
1324                                        if Core.roottry > 5 :
1325                                                Core.roottry = 0
1326                                                self.master_password=generate_rootpasswd()
1327                                                global master_password
1328                                                master_password=self.master_password
1329                                        return AUTHENTICATION_ERROR
1330                        else:
1331                                user="anonymous"
1332                                validate=False
1333                                grouplist=[]
1334                                grouplist.append("anonymous")
1335                                user_found=True
1336
1337
1338               
1339                lets_pam=True
1340
1341                if validate:
1342                        if user in self.credentials:
1343                                try:
1344                                        if self.credentials[user] == password:
1345                                                print("[CREDENTIALS CACHE] FOUND")
1346                                                user_found=True
1347                                                paux = subprocess.Popen(["groups",user],stdout = subprocess.PIPE,stderr = subprocess.PIPE)
1348                                                cnaux = paux.stdout.readline().replace("\n","")
1349                                                grouplist = cnaux.split(":")[1].lstrip().split(" ")
1350                                                grouplist.append('*')
1351                                                grouplist.append('anonymous')                                           
1352                                                user_found=True
1353                                                lets_pam=False
1354                                               
1355                               
1356                                except Exception as e:
1357                                        #print(e)
1358                                        pass
1359                               
1360                               
1361                        if "NTicketsManager" in objects:
1362                               
1363                                if objects["NTicketsManager"].validate_user(user,password):
1364                                        print("[NTicketsManager] TICKET FOUND")
1365                                        user_found=True
1366                                        paux = subprocess.Popen(["groups",user],stdout = subprocess.PIPE,stderr = subprocess.PIPE)
1367                                        cnaux = paux.stdout.readline().replace("\n","")
1368                                        grouplist = cnaux.split(":")[1].lstrip().split(" ")
1369                                        grouplist.append('*')
1370                                        grouplist.append('anonymous')                                           
1371                                        user_found=True
1372                                        lets_pam=False
1373                                                       
1374                        if lets_pam and not user_found:
1375                                       
1376                                aux = PamValidate()
1377                                if aux.authentication(user,password):
1378                                        paux = subprocess.Popen(["groups",user],stdout = subprocess.PIPE,stderr = subprocess.PIPE)
1379                                        cnaux = paux.stdout.readline().replace("\n","")
1380                                        grouplist = cnaux.split(":")[1].lstrip().split(" ")
1381                                        grouplist.append('*')
1382                                        grouplist.append('anonymous')                                   
1383                                        user_found=True
1384                                        self.credentials[user]=password
1385                                else:
1386                                        user_found=False
1387
1388               
1389                if user_found:
1390               
1391                        for plugin in cm.plugins:
1392                                for m in plugin.function:
1393                                        if m==method and plugin.class_name==class_name:
1394                                                self.dprint("\tThis function can be executed by: %s"%plugin.function[m])
1395                                                for group in grouplist:
1396                                                        if group in plugin.function[m] or group=="root":
1397
1398                                                                count=0
1399                                                                tmp=list(new_params)
1400                                                               
1401                                                                if len(tmp)>0:
1402                                                                        for item in plugin.secure_order:
1403                                                                                secure_type,variable_name=item
1404                                                                                if len(secure_type)>0:
1405                                                                                        if m in secure_type:
1406                                                                                                tmp_count=count
1407                                                                                                while tmp_count >= len(tmp):
1408                                                                                                        tmp_count-=1
1409                                                                                                tmp[tmp_count]=locals()[variable_name]
1410                                                                                       
1411                                                                                        count+=1
1412                                                                                       
1413                                                                new_params=tuple(tmp)
1414                                                                return (RUN,new_params)
1415                                                       
1416                                                return NOT_ALLOWED     
1417                                               
1418                       
1419                        if Core.learn:
1420                               
1421                                print "trying skynet:" + Core.skynet
1422                                server = xmlrpclib.ServerProxy(Core.skynet)
1423                               
1424                                lessons=server.get_sorted_methods()
1425                                print lessons
1426                                for lesson in lessons:
1427                                        print lesson,"=?",class_name
1428                                        if lesson == class_name:
1429                                                print 3
1430                                                for chapter in lessons[class_name]:
1431                                                        print "!",chapter,"=?", method
1432                                                        if chapter == method:
1433                                                                print 4
1434                                                                data=server.get_lesson("","LessonManager",lesson)
1435                                                                print 5
1436                                                                print data
1437                                                                if data!=False:
1438                                                                        plugin_info,code=data
1439                                                                        print "Trying to learn..."
1440                                                                       
1441                                                                        plug=PluginInfo()
1442                                                                       
1443                                                                        plug.path=plugin_info["path"]
1444                                                                        plug.type=plugin_info["type"]
1445                                                                        plug.class_name=plugin_info["class_name"]
1446                                                                        plug.function=plugin_info["function"]
1447                                                                        plug.bin_name=plugin_info["bin_name"]
1448                                                                        plug.args=plugin_info["args"]
1449                                                                       
1450                                                                        load_external_module(code,plug)
1451                                                                       
1452                                                                        print "Now I know " + plug.class_name
1453                                                                       
1454                                                                        return self.validate_function(user_password,class_name,method,new_params)
1455                                                                       
1456                       
1457                        return METHOD_NOT_FOUND
1458                       
1459                else:
1460                        return AUTHENTICATION_ERROR # USER NOT FOUND
1461                       
1462               
1463               
1464        #def validate_function
1465                                       
1466
1467       
1468#class core
1469
1470if __name__=="__main__":
1471        core=Core()
1472       
1473       
Note: See TracBrowser for help on using the repository browser.