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

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

wip

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