OSSIM open source security information management system


(continued from the previous article:)

__ daemonize__(self): daemon method

If you receive the signal.SIGTERM (terminate the process), call self.stop
When the user enters kill sigterm pid. The corresponding process will receive this signal. The signal process can capture and specify function processing, such as program cleaning, or ignore this signal

def __daemonize__(self):
    signal.signal(signal.SIGTERM, self.stop)

Create a child process

    pid = os.fork()
    #If pid > 0, it indicates that it is currently in the parent process (the value of pid is the process number of the child process)
    if pid > 0:
        #Exit the first parent process
#Failed to create the child process, and the corresponding error message is output
except OSError, e:
    sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))

Decouple from parent environment

os.setsid(): when the process is the leading process of the session, the setsid() call fails and returns (- 1).
After the setsid() call is successful, the ID of the new session is returned. The process calling the setsid function becomes the leader process of the new session and is separated from the session group and process group of its parent process.

# The os.chdir() method is used to change the current working directory to the specified path.
#Call system call setsid()
#Set the current value umask and return the previous umask

Create the second child process, the same process as when creating the first child process

    pid = os.fork()
    if pid > 0:
        #Exit the second parent process
except OSError, e:
    sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))

Redirect standard file descriptor

sys.stdout.flush(), sys.stderr.flush(): standard output and standard error stream


file(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None):

r: Open the file as read-only. The pointer to the file will be placed at the beginning of the file. This is the default mode.

A +: open a file for reading and writing. If the file already exists, the file pointer will be placed at the end of the file. The file is opened in append mode. If the file does not exist, create a new file for reading and writing.

0: error level

si = file('/dev/null', 'r')
so = file('/dev/null', 'a+')
se = file('/dev/null', 'a+', 0)

os.dup2(): used to copy one file descriptor FD to another file descriptor fd2.
fileno(): returns an integer file descriptor (FD integer), which can be used for I/O operations of the underlying operating system.

Copy input, output, error file descriptors to standard input, standard output, standard error stream

os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())

Write pid file

atexit.register(): used to register an exit function in the python interpreter. This function is automatically executed when the interpreter terminates normally. It is generally used to clean up resources (here is to delete pid files)

pid = str(os.getpid())
file(self.pidfile, 'w+').write("%s\n" % pid)
os.chmod(self.pidfile, 0644)

delpid(self): deletes the pid file

def delpid(self):
    Delete the pid file

stop(self, sig, params): terminate the frameworkd process

def stop(self, sig, params):
       pf = file(self.pidfile, 'r')
       pid = int(pf.read().strip())
    except IOError:
       pid = None
    if not pid:
       message = "pidfile %s does not exist. Daemon not running? or not in daemon mode?\n"
       sys.stderr.write(message % self.pidfile)

Terminate daemon

    while 1:
        os.kill(pid, signal.SIGTERM)
except OSError, err:
    err = str(err)
    if err.find("No such process") > 0:
        if os.path.exists(self.pidfile):
    print str(err)

Wait forever (self): wait for Control-C and terminate all threads

def waitforever(self):

    while 1:
            #The isAlive method inherits from threading, is_ The alive () method queries whether the thread is still running
            if not self.__listener.isAlive():
                logger.info("Listener in down... exiting...")
                pid = os.getpid()
                os.kill(pid, signal.SIGKILL)
        except KeyboardInterrupt:
            pid = os.getpid()
            os.kill(pid, signal.SIGKILL)

__init_log(self, daemon_mode)

def __init_log(self, daemon_mode):
    verbose = "info"
    Logger.add_file_handler('%s/frameworkd.log' % self.__conf[VAR_LOG_DIR])
    Logger.add_error_file_handler('%s/frameworkd_error.log' % self.__conf[VAR_LOG_DIR])

    if daemon_mode:

The command line function was parsed earlier__ parse_ - v parameter in options (self)
parser.add_option("-v", "--verbose", dest="verbose", action="count",help="make lots of noise")

Command line parameters
-v -> self.options.verbose = 1
-vv -> self.options.verbose = 2

if self._options.verbose is not None:
    for i in range(self._options.verbose):
        verbose = Logger.next_verbose_level(verbose)
    os.chmod('%s/frameworkd.log' % self.__conf[VAR_LOG_DIR], 0644)
    os.chmod('%s/frameworkd_error.log' % self.__conf[VAR_LOG_DIR], 0644)
except Exception, e:
    print str(e)

Check encryption key (self): check the encryption key file.

Check whether the file exists and whether the key is stored in the database

def checkEncryptionKey(self):
    mydb = OssimDB(self.__conf[VAR_DB_HOST], self.__conf[VAR_DB_SCHEMA],
                   self.__conf[VAR_DB_USER], self.__conf[VAR_DB_PASSWORD])
    select_query = "select value from config where conf=\"encryption_key\";"
    insert_query = "REPLACE INTO config VALUES ('encryption_key', '%s')"
    data = mydb.exec_query(select_query)
        keyFilePath = self.__conf[VAR_KEY_FILE]
        if keyFilePath == "" or keyFilePath is None:
            logger.error("Frameworkd can't start. Please check the value of %s in the config table" % VAR_KEY_FILE)

        if not os.path.isfile(self.__conf[VAR_KEY_FILE]) or data is None or data == "" or len(data) == 0:
                "Encryption key file doesn't exist... making it at .. %s and save it to db" % self.__conf[VAR_KEY_FILE])
            output = sub.Popen('/usr/bin/alienvault-system-id', stdout=sub.PIPE)
            s_uuid = output.stdout.read().upper()
            reg_str = "(?P<uuid>[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12})"
            pt = re.compile(reg_str, re.M)
            match_data = pt.search(s_uuid)
            key = ""
            extra_data = ""
            d = datetime.today()
            if match_data is not None:
                key = match_data.group('uuid')
                extra_data = "#Generated using alienvault-system-id\n"
                    "I can't obtain system uuid. Generating a random uuid. Please do backup your encrytion key file: %s" %
                extra_data = "#Generated using random uuid on %s\n" % d.isoformat(' ')
                key = uuid.uuid4()
            newfile = open(self.__conf[VAR_KEY_FILE], 'w')
            mydb.exec_query(insert_query % key)
            key = "key=%s\n" % key
            newfile.write("#This file is generated automatically by ossim. Please don't modify it!\n")
            # insert the key in db..
            pw = pwd.getpwnam('www-data')
            os.chown(self.__conf[VAR_KEY_FILE], pw.pw_uid, pw.pw_gid)
            os.chmod(self.__conf[VAR_KEY_FILE], stat.S_IRUSR)

__ check_pid(self): check whether the pid file exists

def __check_pid(self):
        pf = file(self.pidfile, 'r')
        pid = int(pf.read().strip())
    except IOError:
        pid = None
    if pid:
        message = "pidfile %s already exist. Daemon already running?\n"
        sys.stderr.write(message % self.pidfile)

Previous (Framework source code analysis (I)): OSSIM open source security information management system (V)
Next (Framework source code analysis (III)):

Tags: Operation & Maintenance security

Posted on Fri, 15 Oct 2021 17:16:05 -0400 by titoni