Beispiel #1
0
def initSessions():
    global sessionLock
    try:
        # Get database connection parameters
        _dhost = config_get("database", "host")
        ccsd_session.dhost = _dhost!="" and _dhost or None
	log_info("host = %s" % ccsd_session.dhost)

        _ddatabase = config_get("database", "database")
        ccsd_session.database = _ddatabase!="" and _ddatabase or None
	log_info("database = %s" % ccsd_session.database)

        _duser = config_get("database", "user")
        ccsd_session.duser = _duser!="" and _duser or None
	log_info("duser = %s" % ccsd_session.duser)

        _dpass = config_get("database", "password")
        ccsd_session.dpass = _dpass!="" and _dpass or None

        # Does the admin want us to log query times
        ccsd_session.log_times = config_getboolean(None, "log_db_times", False)

        # Create a program wide 'admin' session which is always present
        ccsd_session.sessions[ADMIN_SESSION_ID] = \
                ccsd_session("admin", SESSION_RW, "", -1, -1, ADMIN_SESSION_ID)

        # Load any other saved sessions
        ccsd_session.sessions.update(loadSessions())
        
        # Initialise the lock
        sessionLock = threading.RLock()

        log_info("Successfully loaded sessions")
    except:
        log_fatal("Failed to load initial program state!", sys.exc_info())    
Beispiel #2
0
def send_mail(send_from, send_to, subject, text, files=[], cc=[], bcc=[]):
    """Send an email, optionally with some attachments"""
    from ccsd_config import config_get

    # Try and read the server and domain from the config file, but this 
    # might fail, if it hasn't been started yet
    try:
        server = config_get("network", "smtp_server", "localhost")
    except:
        server = "localhost"
    try:
        domain = config_get("network", "domain")
    except:
        domain = "localhost"

    # Ensure the sender address is fully qualified
    if send_from.find("@") == -1:
        send_from = "%s@%s" % (send_from, domain)

    # Create the MIME message
    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = COMMASPACE.join(send_to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    # Handle Carbon-copy recipients
    if len(cc) > 0:
        msg['CC'] = COMMAPSACE.join(cc)
        send_to.extend(cc)

    # Handle Blind-carbon-copy recipients
    if len(bcc) > 0:
        send_to.extend(bcc)

    # Attach the message text
    msg.attach( MIMEText(text) )

    # Attach files
    for f in files:
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(f,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 
                'attachment; filename="%s"' % os.path.basename(f))
        msg.attach(part)

    # Send the message
    smtp = smtplib.SMTP(server)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.close()
    return True
Beispiel #3
0
def startCCSDServer(key, cert, cacert):
    """Initialises the CCSD Server.

    This function never returns as it enters a mainloop
    """
    global server_running, recurring

    try:
        # Port and logfile
        port = int(config_get(None, "port", DEFAULT_CLIENT_PORT))
        logfile = config_get(None, "request_log", DEFAULT_REQUEST_LOG)

        # Initialise an HTTP server
        httpd = AsyncHTTPServer(('', port), CCSDHandler)
        log_info("Server Started. Ready to serve requests...")
        server_running = True
    except:
        log_fatal("Could not initialise the server!", sys.exc_info())

    # Start the mainloop
    while server_running:
        try:
            # Check recurring functions to see if they need to be called
            now = time.time()
            for sched_time, func in recurring.items():
                if sched_time <= now:
                    try:
                        func()
                    except:
                        log_error("Unknown error in recurring function!", \
                                sys.exc_info())
                    del recurring[sched_time]
                    newTime = sched_time + func._interval
                    recurring[newTime] = func
            # put in a timeout so we don't monopolise the CPU
            asyncore.poll(30)
        except socket.error:
            # Socket operation died, ignore
            log_error("Socket operation failed! Continuing.", sys.exc_info())
            continue
        except SystemExit:
            # Ignore, server_running will be set to false shortly
            continue
        except:
            # Unknown ERROR
            (etype, value, tb) = sys.exc_info()
            log_error("Unexpected error caught by mainloop! - %s" % value, 
                    (etype, value, tb))
Beispiel #4
0
    def _doCertificateLogon(self, request):
        """Attempt to logon using the client certificate
        
        This can only succeed if:
        * the client certificate CN matches a username 
        * cert_logins is not disabled in the configuration file
        """
        from ccsd_session import startSession, startBasicSession
        from crcnetd.modules.ccs_contact import getUserCache
        
        # Check incoming peer certificate
        cert = request.channel.transport.socket.get_peer_certificate()
        subj = cert.get_subject()
        domain = config_get('network','domain', '')
        username = "******" % (subj.CN , domain)

        allow_login = config_getboolean(None, "cert_logins", True)
        if not allow_login:
            None
            # CN matches a MAC address
            #return startBasicSession(username, SESSION_RW)
        
        # Does the CN match a username?
        users = getUserCache(ADMIN_SESSION_ID)
        if username in users.keys():
            if users[username]["enabled"]:
                # Make sure a session exists for the user
                return startSession(users[username]['login_id'], SESSION_RW)
            
        # CN matches a MAC address
        #return startBasicSession(username, SESSION_RW)
        return None
Beispiel #5
0
def handleDaemonise():
    
    # Read command line options
    is_daemon = 0
    optlist, args = getopt.gnu_getopt(sys.argv[1:], OPTION_LIST)
    for (arg, val) in optlist:
        if arg == "-d":
            is_daemon = daemonise()

    # Make sure logger knows our status
    setDaemonStatus(is_daemon)
    setTracebackLog(config_get(None, "traceback_log", None))
Beispiel #6
0
def daemonise():
    """Detach a process from the controlling terminal and run it in the
    background as a daemon.

    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
    """
    
    # Get pidfile location
    pidfile = config_get(None, "pidfile", DEFAULT_PIDFILE)
    
    # Check pidfile is writable
    if os.access(os.path.dirname(pidfile), os.W_OK) != 1:
        log_fatal("Unable to write to pid file (%s)" % pidfile)
        
    try:
        pid = os.fork()
    except OSError, e:
        raise Exception, "%s [%d]" % (e.strerror, e.errno)
Beispiel #7
0
def startCCSDServer(key, cert, cacert):
    """Initialises the CCSD Server.

    This function never returns as it enters the twisted mainloop
    """

    try:           
        # Local networks
        localnets = config_get(None, "local_networks", "127.0.0.0/8")

        # Register standard HTTP XMLRPC handler for local requests
        registerHTTPResource("RPC2", ccsd_local_xmlrpc, 
                localnets=localnets.split(","))

        # Register HTTPS XMLRPC Handler
        use_ssl = config_getboolean(None, "use_ssl", True)
        if use_ssl:
            registerHTTPSResource("RPC2", ccsd_xmlrpc)

        # Setup XMLRPC Handler configuration
        ccsd_xmlrpc.log_times = config_get(None, "log_times", None)
        ccsd_xmlrpc.profile = config_getboolean(None, "profile", False)
        ccsd_xmlrpc.prof_dir = config_get(None, "profile_dir", \
                DEFAULT_PROFILE_DIR)
        ccsd_xmlrpc.log_threads = config_get(None, "log_threads", None)
        ccsd_xmlrpc.max_threads = config_getint(None, "max_threads", 
                DEFAULT_MAX_THREADS)

        # SSL Context
        class SCF:
            def __init__(self, key, cert, cacert):
                self.mKey = key
                self.mCert = cert
                self.mCACert = cacert
                
            def verify(self, conn, cert, errnum, depth, ok):
                """Checks the certificate of an incoming connection"""
                # If there is already an error bail now
                if not ok:
                    return ok
                
                # Only perform further verification on client certs
                if depth>0:
                    return ok
                
                # At this point we know the certificate is signed by a 
                # trusted CA, check the issuer OU matches the incoming cert
                # OU and the incoming cert is not a server cert
                # XXX: Should look at using something like nsCertType rather
                # than the CN field for this.
                s = cert.get_subject()
                i = cert.get_issuer()
                if s.OU != i.OU:
                    log_warn("Rejected incoming connection from invalid " 
                            "SSL cert (%s). OU did not match." % s)
                    return 0
                if s.CN == "server":
                    log_warn("Rejected incoming connection from server SSL "
                            "cert (%s)." % s)
                    return 0
                return 1
                
            def getContext(self):
                """Create an SSL context."""
                ctx = SSL.Context(SSL.SSLv2_METHOD)
                # Add the CA certificate(s)
                store = ctx.get_cert_store()
                for cert in self.mCACert:
                    store.add_cert(cert)
                # Load the private key and certificate
                ctx.use_privatekey(self.mKey)
                ctx.use_certificate(self.mCert)
                ctx.set_verify(SSL.VERIFY_PEER | 
                        SSL.VERIFY_FAIL_IF_NO_PEER_CERT, self.verify)
                ctx.set_verify_depth(len(self.mCACert))
                return ctx

        # Port and logfile
        http_port = int(config_get(None, "http_port", 
            DEFAULT_HTTP_SERVER_PORT))
        https_port = int(config_get(None, "https_port", 
            DEFAULT_HTTPS_SERVER_PORT))
        logfile = config_get(None, "request_log", DEFAULT_REQUEST_LOG)

        # Pass off control to Twisted's mainloop
        threadable.init()
        suggestThreadpoolSize(ccsd_xmlrpc.max_threads)
        reactor.listenTCP(http_port, server.Site(_http_root, logfile))
        if use_ssl:
            reactor.listenSSL(https_port, server.Site(_https_root, logfile), \
                    SCF(key, cert, cacert))
        reactor.addSystemEventTrigger("before", "shutdown", shutdownHandler)
        log_info("Server Started. Ready to serve requests...")
    except:
        log_fatal("Could not initialise the server!", sys.exc_info())

    reactor.run()
Beispiel #8
0
def loadModules(opmode):
    """Loads modules appropriate for the current server"""
    
    # Initialise modules
    mDir = "%s/modules" % os.path.dirname(os.path.dirname(__file__))
    dMods = config_get(None, "modules", None)
    if dMods is None:
        return []
    modules = []

    if opmode == CCSD_SERVER:
        prefix = "ccs"
    else:
        prefix = "ccs_monitor"

    # Scan through the list and load valid modules
    for module in dMods.split(","):
        module = module.strip()
        if module == "":
            continue
        mname = "%s_%s" % (prefix, module)
        mfile = "%s/%s.py" % (mDir, mname)
        # Check module exists
        if not os.path.exists(mfile):
            log_fatal("Cannot load requested module '%s'. File not found!" % \
                    module)
        # Load the modules code
        fd = open(mfile, "r")
        data = fd.read()
        fd.close()
        # Look for a line containing ccsd_mod_type
        idx = data.find("ccs_mod_type")
        if idx == -1:
            log_fatal("Module '%s' has no ccs_mod_type property!" % module)
        try:
            code = compile(data[idx:data.find("\n",idx)], "%s.py" % mname, \
                    'single')
            eval(code)
            if ccs_mod_type is None:
                log_fatal("Could not determine type of module '%s'!" % module)
            if type(ccs_mod_type)==type([]):
                if opmode not in ccs_mod_type:
                    log_fatal("Module '%s' cannot be used with this mode!" % \
                            module)
                    continue
            else:
                if opmode != ccs_mod_type:
                    log_fatal("Module '%s' cannot be used with this mode!" % \
                            module)
                    continue
        except:
            log_fatal("Could not determine type of module '%s'!" % module, \
                    sys.exc_info())
        # Load the module 
        try:
            exec "import crcnetd.modules.%s" % mname
            m = eval("crcnetd.modules.%s" % mname)
        except:
            log_fatal("Module '%s' failed to load!" % module, sys.exc_info())
        modules.append(m)
        log_info("Loaded Module: %s" % module)
   
    return modules