def __init__(self,
                 rssUrlList,
                 updateDuration=1800,
                 observers=[],
                 log=None):
        self.rssUrlList = rssUrlList
        self.updateDuration = updateDuration
        self.observers = observers
        self.log = log
        self.preferences = Preferences()

        self.entries = {}

        self._StartTimer()
Beispiel #2
0
def main():
    prefs = Preferences()
    registryClient = RegistryClient(
        'http://www.accessgrid.org/registry/peers.txt')
    bridgeList = prefs.GetBridges()
    bridgePinger = BridgePingThread(prefs, registryClient, bridgeList.values())
    bridgePinger.start()

    while 1:
        bridges = prefs.GetBridges().values()
        bridges.sort(lambda x, y: BridgeDescription.sort(x, y, 1))
        for b in bridges:
            print '%2.5f %s' % (b.rank, b.name)
        print 'sleeping for ', bridgePinger.refreshDelay
        time.sleep(bridgePinger.refreshDelay)
Beispiel #3
0
def BuildPreferencesProxyURL():
    """Build a proxy URL based on the settings in the preferences file"""
    from AccessGrid.Preferences import Preferences

    preferences = Preferences()
    proxyUsername = None
    proxyPassword = None

    proxyEnabled = int(preferences.GetPreference(Preferences.PROXY_ENABLED))
    if not proxyEnabled:
        return ""

    if int(preferences.GetPreference(Preferences.PROXY_AUTH_ENABLED)) == 1:
        proxyUsername = preferences.GetPreference(Preferences.PROXY_USERNAME)
        proxyPassword = preferences.GetProxyPassword()

    return BuildProxyURL(preferences.GetPreference(Preferences.PROXY_HOST), \
                         preferences.GetPreference(Preferences.PROXY_PORT), \
                         proxyUsername, \
                         proxyPassword)
Beispiel #4
0
class AppBase:
    """
    The application object is one of the top level objects used to
    build new parts of the AGTk. The application object is required to
    be a singleton in any process.
    """
    # The singleton
    theInstance = None

    # The class method for retrieving/creating the singleton
    def instance():
        """
        The interface for getting the one true instance of this object.
        """
        return AppBase.theInstance

    instance = staticmethod(instance)

    def set_instance(obj):
        AppBase.theInstance = obj

    set_instance = staticmethod(set_instance)

    # The real constructor
    def __init__(self):
        """
       The application constructor that enforces the singleton pattern.
       """
        if AppBase.instance():
            raise Exception, "Only one instance of AppBase is allowed; already have instance of %s" % (
                AppBase.instance().__class__, )

        AppBase.set_instance(self)

        self.parser = OptionParser()
        self.parser.add_option("-d",
                               "--debug",
                               action="store_true",
                               dest="debug",
                               default=0,
                               help="Set the debug level of this program.")
        self.parser.add_option("-l",
                               "--logfile",
                               dest="logfilename",
                               metavar="LOGFILE",
                               default=None,
                               help="Specify a log file to output logging to.")
        self.parser.add_option(
            "--numlogfiles",
            dest="numlogfiles",
            metavar="NUMLOGFILES",
            default=1,
            type="int",
            help="Specify the number of log files to retain")
        self.parser.add_option("--logfilesize",
                               dest="logfilesize",
                               metavar="LOGFILESIZE",
                               default=10000000,
                               type="long",
                               help="Specify the size of log files to retain")
        self.parser.add_option(
            "-c",
            "--configfile",
            dest="configfilename",
            metavar="CONFIGFILE",
            default=None,
            help="Specify a configuration file for the program.")
        self.parser.add_option(
            "--version",
            action="store_true",
            dest="version",
            default=0,
            help="Print out what version of the toolkit this is.")
        self.parser.add_option("--secure",
                               type="int",
                               dest="secure",
                               default=0,
                               help="Specify whether the service uses SSL.")
        self.parser.add_option("--cert",
                               dest="cert",
                               metavar="CERTFILE",
                               default=None,
                               help="Specify a certificate file to use.")
        self.parser.add_option("--key",
                               dest="key",
                               metavar="KEYFILE",
                               default=None,
                               help="Specify a certificate key file to use.")
        self.parser.add_option(
            "--cadir",
            dest="cadir",
            metavar="CADIR",
            default=None,
            help="Specify the directory containing CA certificates.")

        self.options = None
        self.userConfig = None
        self.agtkConfig = None
        self.systemConfig = SystemConfig.instance()
        self.log = None
        self.loggerLevels = None
        self.fhLoggerLevels = None

        self._certificateManager = None
        self._certMgrUI = None

        # This initializes logging
        self.log = Log.GetLogger(Log.Toolkit)
        self.log.debug("Initializing AG Toolkit version %s %s", GetVersion(),
                       GetStatus())
        self.log.info("Command and arguments: %s" % sys.argv)

        self.__context = None
        self.__passphrase = None

    # This method implements the initialization strategy outlined
    # in AGEP-0112
    def Initialize(self, name=None, args=None):
        """
       This method sets up everything for reasonable execution.
       At the first sign of any problems it raises exceptions and exits.
       """
        self.name = name

        # 1. Process Command Line Arguments
        argvResult = self.ProcessArgs(args=args)

        # 2. Load the Toolkit wide configuration.
        try:
            self.agtkConfig = AGTkConfig.instance(0)
        except Exception:
            self.log.exception("Toolkit Initialization failed.")
            sys.exit(-1)

        # 3. Load the user configuration, creating one if necessary.
        try:
            self.userConfig = UserConfig.instance(initIfNeeded=1)
        except Exception:
            self.log.exception("User Initialization failed.")
            sys.exit(-1)

        # Load client preferences
        self.preferences = Preferences()
        self.ProcessArgsThatUsePreferences()

        # 4. Redirect logging to files in the user's directory,
        #    purging memory to file

        fh = Log.defLogHandler

        if self.options.logfilename is not None:
            if not self.options.logfilename.endswith(".log"):
                self.name = self.options.logfilename + ".log"
            else:
                self.name = self.options.logfilename
        elif self.name is not None:
            if not self.name.endswith(".log"):
                self.name = self.name + ".log"

        self.log.info("Logfile Name: %s", self.name)

        if self.name:
            if not self.name.startswith(os.sep) \
                                      and not self.name.startswith("."):
                filename = os.path.join(self.userConfig.GetLogDir(), self.name)
            else:
                filename = self.name

            fh = Log.RotatingFileHandler(filename, "a",
                                         self.options.logfilesize,
                                         self.options.numlogfiles)

            fh.setFormatter(Log.GetFormatter())
            self.fhLoggerLevels = Log.HandleLoggers(fh,
                                                    Log.GetDefaultLoggers())
            self.fhLoggerLevels.SetLevel(Log.DEBUG)
            self.fhLoggerLevels.SetLevel(Log.CRITICAL, Log.RTPSensor)
            self.loggerLevels = self.fhLoggerLevels

            # Send the log in memory to stream (debug) or file handler.
        if self.options.debug or int(
                self.preferences.GetPreference(Preferences.LOG_TO_CMD)):
            Log.mlh.setTarget(Log.defStreamHandler)
        else:
            Log.mlh.setTarget(fh)
        Log.mlh.close()
        Log.RemoveLoggerLevels(Log.memLevels, Log.GetLoggers())

        self.__SetLogPreference()

        self.CheckDependencies()

        # Check if machine clock is synchronized.
        # - Disabled for 3.0: clock-sync is important when using proxy certs, which we're not
        #self.__CheckForInvalidClock()

        self.__context = None

        return argvResult

    def CheckDependencies(self):
        if not hasattr(socket, 'ssl'):
            raise MissingDependencyError("SSL")

    def GetContext(self):
        # Hack to allow use of proxy certs, until the necessary
        # interface is exposed through M2Crypto
        os.environ['OPENSSL_ALLOW_PROXY_CERTS'] = '1'

        certManager = self.GetCertificateManager()
        caDir = self._certificateManager.caDir
        """
        Logic here is like so:
        
        If we haven't created a context
            - create one
        If the default identity has an encrypted private key
            - If a valid proxy certificate exists
                - If the current context is not using the proxy cert
                    - Make it so
            - Else
                - Create a proxy certificate
                - Configure the context to use the proxy certificate
        Else    
            - If the current context is not using the default certificate
                - Make it so
        """
        # Create the SSL context if needed
        if not self.__context:
            self.__context = SSL.Context('sslv23')
            self.__context.load_verify_locations(capath=caDir)
            #self.__context.set_verify(SSL.verify_peer,10,self.VerifyCallback)
            self.__context.set_verify(SSL.verify_peer, 10)
            self.__context.set_session_id_ctx('127.0.0.1:8006')
            self.__context.set_cipher_list('LOW:TLSv1:@STRENGTH')

        # if the private key is encrypted, we need a proxy certificate
        id = self.GetCertificateManager().GetDefaultIdentity()
        if id.HasEncryptedPrivateKey():
            # - if a valid proxy does exists, confirm that it's being used
            if certManager.HaveValidProxy():
                # Should confirm that proxy is being used by context;
                # for now, just force it to be used
                id = certManager.GetProxyCert()
                self.log.info('Using proxy certificate: %s %s', id.GetPath(),
                              id.GetKeyPath())
                self.__context.load_cert_chain(id.GetPath(), id.GetKeyPath())
            else:
                # create a proxy and use it
                certManager.CreateProxyCertificate()
                id = certManager.GetProxyCert()
                self.log.info('Using proxy certificate: %s %s', id.GetPath(),
                              id.GetKeyPath())
                self.__context.load_cert_chain(id.GetPath(), id.GetKeyPath())

        else:
            # Should confirm that certificate is being used by context;
            # for now, just force it to be used
            self.log.info('Using unencrypted certificate: %s %s', id.GetPath(),
                          id.GetKeyPath())
            self.__context.load_cert(id.GetPath(), id.GetKeyPath())

        return self.__context

    def VerifyCallback(self, ok, store):
        # unused, except possibly for debugging
        self.log.info('VerifyCallback: ok,store=%d %s %s' %
                      (ok, store.get_current_cert().get_subject().as_text(),
                       store.get_error()))
        return 1

    def __SetLogPreference(self):
        """
        Set correct log level for each log category according
        to preferences.
        """
        logFiles = Log.GetCategories()

        for name in logFiles:
            # Get level from preferences.
            logLevel = int(self.preferences.GetPreference(name))
            fLevels = self.GetFileLogLevels()
            sLevels = self.GetStreamLogLevels()

            # Level for files
            if fLevels:
                fLevels.SetLevel(logLevel, name)
            # Level for streams
            if sLevels:
                sLevels.SetLevel(logLevel, name)

    def __CheckForInvalidClock(self):
        """
       Check to see if the local clock is out of synch, a common reason for a
       failed authentication.
       
       This routine loggs a warningString.
       """

        timeserver = "ntp-1.accessgrid.org"
        timeout = 0.3
        maxOffset = 10

        try:
            serverTime = GetSNTPTime(timeserver, timeout)
        except:
            self.log.exception(
                "Toolkit.__CheckForValidClock: Connection to sntp server at %s failed",
                timeserver)
            serverTime = None

        if serverTime is not None:

            diff = int(time.time() - serverTime)
            absdiff = abs(diff)

            if absdiff > maxOffset:

                if diff > 0:
                    direction = "fast"
                else:
                    direction = "slow"

                warningString = ("The machine clock is incorrect on\n" + \
                                 "your computer: it is %s seconds %s with respect\n" + \
                                 "to the time server at %s.") % \
                                 (absdiff, direction, timeserver)

                self.log.warn("Toolkit.__CheckForValidClock: %s" %
                              warningString)

    def ProcessArgs(self, args=None):
        """
       Process toolkit wide standard arguments. Then return the modified
       argv so the app can choose to parse more if it requires that.
       """

        if args == None:
            (self.options, ret_args) = self.parser.parse_args()
        else:
            (self.options, ret_args) = self.parser.parse_args(args=args)

        if self.options.version:
            print "Access Grid Toolkit Version: ", GetVersion()
            sys.exit(0)

        if self.options.cert:
            self.options.secure = 1

        return ret_args

    def ProcessArgsThatUsePreferences(self):
        """
       Process toolkit wide logging arguments. Then return the modified
       argv so the app can choose to parse more if it requires that.
       """

        if self.options.debug or int(
                self.preferences.GetPreference(Preferences.LOG_TO_CMD)):
            self.streamLoggerLevels = Log.HandleLoggers(
                Log.defStreamHandler, Log.GetDefaultLoggers())
            self.streamLoggerLevels.SetLevel(Log.DEBUG)
            self.streamLoggerLevels.SetLevel(Log.CRITICAL, Log.RTPSensor)
            # When in debug mode, we'll make the stream the primary handler.
            self.loggerLevels = self.streamLoggerLevels
        else:
            # If not in debug, we only used the StreamHandler before Logging was initialized.
            #    so we don't have a StreamLoggerLevels.
            self.streamLoggerLevels = None

    def AddCmdLineOption(self, option):
        self.parser.add_option(option)

    def SetCmdLineDefault(self, option, value):
        if self.parser.defaults.has_key(option):
            self.parser.defaults[option] = value
        else:
            self.log.error('SetCmdLineDefault called with invalid option: %s',
                           option)

    def GetPreferences(self):
        '''
        Get client preferences. 
        '''
        return self.preferences

    def SetPreferences(self, preferences):
        '''
        Set preferences and save them to configuration file.
        '''
        self.preferences = preferences
        self.preferences.StorePreferences()

    def GetOption(self, arg):

        if hasattr(self.options, arg):
            return getattr(self.options, arg)
        else:
            return None

    def GetDebugLevel(self):
        """
        """
        return self.GetOption("debug")

    def GetLogFilename(self):
        """
        """
        return self.GetOption("logfilename")

    def GetConfigFilename(self):
        """
        """
        return self.GetOption("configfilename")

    def GetLog(self):
        """
        Return a toolkit wide log.
        """
        return self.log

    def GetLogLevels(self):
        """
        Return the primary loggingLevels object.
          in debug mode: self.streamLoggerLevels
          otherwise:     self.fhLoggerLevels

        Should be called after initialization.
        Levels can be set like this:
            ll = GetFileLevels()
            ll.SetLevel(Log.DEBUG)
        and tuned like this:
            ll.SetLevel(Log.WARN, Log.Hosting)
        """
        return self.loggerLevels

    def GetFileLogLevels(self):
        """
        Return the loggingLevels object for the current log file.
        """
        return self.fhLoggerLevels

    def GetStreamLogLevels(self):
        """
        Return the loggingLevels object for the current output stream.
        Returns None when not in debug mode.
        """
        return self.streamLoggerLevels

    def GetToolkitConfig(self):
        return self.agtkConfig

    def GetUserConfig(self):
        return self.userConfig

    def GetDefaultSubject(self):
        try:
            ident = self.GetCertificateManager().GetDefaultIdentity()
        except CertificateManager.NoCertificates:
            ident = None

        if ident is not None:
            from AccessGrid.Security import X509Subject
            subject = X509Subject.CreateSubjectFromString(
                str(ident.GetSubject()))
        else:
            subject = None

        return subject

    def GetCertificateManager(self):
        if self._certificateManager == None:
            if self.userConfig == None:
                raise Exception(
                    "No user config dir, Toolkit may not be initialized.")
            configDir = self.userConfig.GetConfigDir()
            self._certificateManager = CertificateManager.CertificateManager(
                configDir)

            self.log.info("Initialized certificate manager.")
            self._certificateManager.InitEnvironment()
        return self._certificateManager

    def GetCertificateManagerUI(self):
        if self._certMgrUI == None:
            # 5. Initialize Certificate Management
            # This has to be done by sub-classes
            from AccessGrid.Security import CertificateManager
            self._certMgrUI = CertificateManager.CertificateManagerUserInterface(
                self.GetCertificateManager())
            # 6. Do one final check, if we don't have a default
            #    Identity we warn them, but they can still request certs.
            #
            self._certMgrUI.InitEnvironment()

            if self.GetDefaultSubject() is None:
                self.log.error("Toolkit initialized with no default identity.")

            self.log.info("Initialized certificate manager UI.")

        return self._certMgrUI

    def GetHostname(self):
        return self.systemConfig.GetHostname()

    def FindConfigFile(self, configFile):
        """
        Locate given file in configuration directories:
        first check user dir, then system dir;
        return None if not found
        """
        if self.userConfig is None:
            self.userConfig = UserConfig.instance()

        pathToFile = os.path.join(self.userConfig.GetConfigDir(), configFile)
        self.log.debug("Looking for: %s", pathToFile)
        if os.path.exists(pathToFile):
            return pathToFile

        pathToFile = os.path.join(self.agtkConfig.GetConfigDir(), configFile)
        self.log.debug("Looking for: %s", pathToFile)
        if os.path.exists(pathToFile):
            return pathToFile

        raise Exception, "File Not Found"
Beispiel #5
0
    def Initialize(self, name=None, args=None):
        """
       This method sets up everything for reasonable execution.
       At the first sign of any problems it raises exceptions and exits.
       """
        self.name = name

        # 1. Process Command Line Arguments
        argvResult = self.ProcessArgs(args=args)

        # 2. Load the Toolkit wide configuration.
        try:
            self.agtkConfig = AGTkConfig.instance(0)
        except Exception:
            self.log.exception("Toolkit Initialization failed.")
            sys.exit(-1)

        # 3. Load the user configuration, creating one if necessary.
        try:
            self.userConfig = UserConfig.instance(initIfNeeded=1)
        except Exception:
            self.log.exception("User Initialization failed.")
            sys.exit(-1)

        # Load client preferences
        self.preferences = Preferences()
        self.ProcessArgsThatUsePreferences()

        # 4. Redirect logging to files in the user's directory,
        #    purging memory to file

        fh = Log.defLogHandler

        if self.options.logfilename is not None:
            if not self.options.logfilename.endswith(".log"):
                self.name = self.options.logfilename + ".log"
            else:
                self.name = self.options.logfilename
        elif self.name is not None:
            if not self.name.endswith(".log"):
                self.name = self.name + ".log"

        self.log.info("Logfile Name: %s", self.name)

        if self.name:
            if not self.name.startswith(os.sep) \
                                      and not self.name.startswith("."):
                filename = os.path.join(self.userConfig.GetLogDir(), self.name)
            else:
                filename = self.name

            fh = Log.RotatingFileHandler(filename, "a",
                                         self.options.logfilesize,
                                         self.options.numlogfiles)

            fh.setFormatter(Log.GetFormatter())
            self.fhLoggerLevels = Log.HandleLoggers(fh,
                                                    Log.GetDefaultLoggers())
            self.fhLoggerLevels.SetLevel(Log.DEBUG)
            self.fhLoggerLevels.SetLevel(Log.CRITICAL, Log.RTPSensor)
            self.loggerLevels = self.fhLoggerLevels

            # Send the log in memory to stream (debug) or file handler.
        if self.options.debug or int(
                self.preferences.GetPreference(Preferences.LOG_TO_CMD)):
            Log.mlh.setTarget(Log.defStreamHandler)
        else:
            Log.mlh.setTarget(fh)
        Log.mlh.close()
        Log.RemoveLoggerLevels(Log.memLevels, Log.GetLoggers())

        self.__SetLogPreference()

        self.CheckDependencies()

        # Check if machine clock is synchronized.
        # - Disabled for 3.0: clock-sync is important when using proxy certs, which we're not
        #self.__CheckForInvalidClock()

        self.__context = None

        return argvResult
class RssReader:
    """
    RssReader takes a list of RSS urls which it should watch,
    updating when the specified duration has expired.
    
    RssReader accepts registration of observers, which will be updated
    with calls to the following methods:
    
        Update
        Error
        
    """
    def __init__(self,
                 rssUrlList,
                 updateDuration=1800,
                 observers=[],
                 log=None):
        self.rssUrlList = rssUrlList
        self.updateDuration = updateDuration
        self.observers = observers
        self.log = log
        self.preferences = Preferences()

        self.entries = {}

        self._StartTimer()

    def Synch(self):
        for rssUrl in self.rssUrlList:
            self._ProcessUrl(rssUrl)

    def _ProcessUrl(self, rssUrl):
        if self.log:
            self.log.debug('Retrieving rss: %s', rssUrl)

        if rssUrl.startswith("file://"):
            rssFile = rssUrl[7:]
            d = feedparser.parse(rssFile)
        else:
            proxyEnabled = int(
                self.preferences.GetPreference(Preferences.PROXY_ENABLED))
            if proxyEnabled:
                proxy = urllib2.ProxyHandler(
                    {"http": Utilities.BuildPreferencesProxyURL()})
                d = feedparser.parse(rssUrl, handlers=[proxy])
            else:
                d = feedparser.parse(rssUrl)

        try:
            channelTime = d['feed']['modified']
            print 'channelTime = ', channelTime
            docDate = strtimeToSecs(channelTime)
        except KeyError:
            docDate = 0

        store = 0
        if rssUrl in self.entries.keys():
            lastDocDate = self.entries[rssUrl][1]
            if lastDocDate < docDate or docDate == 0:
                # document has been updated; store it
                store = 1
        else:
            # new document; store it
            store = 1

        if store:

            if self.log: self.log.debug('Storing rss: %s', rssUrl)

            self.entries[rssUrl] = (d, docDate)

            # Update observers
            map(lambda o: o.UpdateRss(rssUrl, d, docDate), self.observers)

    def SetUpdateDuration(self, updateDuration):

        wereEqual = (self.updateDuration == updateDuration)

        self.updateDuration = updateDuration

        if not wereEqual:
            self._RestartTimer()

    def _RestartTimer(self):
        self.timer.cancel()
        self._StartTimer()

    def _StartTimer(self):
        if self.updateDuration > 0:
            self.timer = threading.Timer(self.updateDuration,
                                         self._TimedUpdate)
            self.timer.start()

    def _TimedUpdate(self):
        try:
            self.Synch()
        except Exception, e:
            print 'exception updating feed:', e
        if self.updateDuration > 0:
            self.timer = threading.Timer(self.updateDuration,
                                         self._TimedUpdate)
            self.timer.start()
Beispiel #7
0
def OpenURL(url):
    """
    This is a proxy-agnostic way of opening a URL and retrieving
    the response. The proxy settings are extracted from the preferences.
    If the connection fails, a dialog is opened to query the user
    for their username and password. This means users do not have to store
    their password in the preferences file, which is insecure to a determined
    attacker.
    """
    from AccessGrid.Preferences import Preferences
    from AccessGrid.UIUtilities import ProxyAuthDialog
    ID_OK = 5100  # hard-coding this for now to avoid importing wx

    preferences = Preferences()
    if int(preferences.GetPreference(Preferences.PROXY_ENABLED)):
        # There is a proxy set, so build the URL of the proxy
        proxySupport = urllib2.ProxyHandler(
            {"http": BuildPreferencesProxyURL()})
        opener = urllib2.build_opener(proxySupport, urllib2.HTTPHandler)
        urllib2.install_opener(opener)

    try:
        response = urllib2.urlopen(url)
    except urllib2.URLError, e:
        errorCode = 0

        # URLError is the superclass of HTTPError, which will return an error
        # code. URLError *won't*, so that has to be extracted with a regex
        if hasattr(e, 'code'):
            errorCode = int(e.code)
        elif hasattr(e, 'reason'):
            # This is a URLError, so extract the error code from reason.
            result = re.search("^\((\d+)", str(e.reason))
            errorCode = int(result.group(1))
            log.debug("URLlib failed: " + str(e.reason))

        # Technically only 407 should come up from a proxy authentication
        # failure
        if errorCode == 407:
            log.info("Proxy authentication failed for: " + url)

            # Only show the dialog if an authenticated proxy was enabled
            if int(preferences.GetPreference(
                    Preferences.PROXY_AUTH_ENABLED)) == 1:
                dialog = ProxyAuthDialog(
                    None, -1, "Check proxy authentication settings")
                dialog.SetProxyUsername(
                    preferences.GetPreference(Preferences.PROXY_USERNAME))
                dialog.SetProxyPassword(preferences.GetProxyPassword())
                dialog.SetProxyEnabled(
                    int(
                        preferences.GetPreference(
                            Preferences.PROXY_AUTH_ENABLED)))

                if dialog.ShowModal() == ID_OK:
                    preferences.SetPreference(Preferences.PROXY_ENABLED, 1)
                    preferences.SetPreference(Preferences.PROXY_USERNAME,
                                              dialog.GetProxyUsername())
                    preferences.SetProxyPassword(dialog.GetProxyPassword())
                    preferences.SetPreference(Preferences.PROXY_AUTH_ENABLED,
                                              dialog.GetProxyEnabled())
                    preferences.StorePreferences()

                    # Try again
                    return OpenURL(url)

        elif hasattr(e, 'reason'):
            log.debug("URLlib failed: " + str(e.reason))
            response = None