This file is indexed.

/usr/share/pyshared/tlslite/SessionCache.py is in python-tlslite 0.3.8-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
"""Class for caching TLS sessions."""

import thread
import time

class SessionCache:
    """This class is used by the server to cache TLS sessions.

    Caching sessions allows the client to use TLS session resumption
    and avoid the expense of a full handshake.  To use this class,
    simply pass a SessionCache instance into the server handshake
    function.

    This class is thread-safe.
    """

    #References to these instances
    #are also held by the caller, who may change the 'resumable'
    #flag, so the SessionCache must return the same instances
    #it was passed in.

    def __init__(self, maxEntries=10000, maxAge=14400):
        """Create a new SessionCache.

        @type maxEntries: int
        @param maxEntries: The maximum size of the cache.  When this
        limit is reached, the oldest sessions will be deleted as
        necessary to make room for new ones.  The default is 10000.

        @type maxAge: int
        @param maxAge:  The number of seconds before a session expires
        from the cache.  The default is 14400 (i.e. 4 hours)."""

        self.lock = thread.allocate_lock()

        # Maps sessionIDs to sessions
        self.entriesDict = {}

        #Circular list of (sessionID, timestamp) pairs
        self.entriesList = [(None,None)] * maxEntries

        self.firstIndex = 0
        self.lastIndex = 0
        self.maxAge = maxAge

    def __getitem__(self, sessionID):
        self.lock.acquire()
        try:
            self._purge() #Delete old items, so we're assured of a new one
            session = self.entriesDict[sessionID]

            #When we add sessions they're resumable, but it's possible
            #for the session to be invalidated later on (if a fatal alert
            #is returned), so we have to check for resumability before
            #returning the session.

            if session.valid():
                return session
            else:
                raise KeyError()
        finally:
            self.lock.release()


    def __setitem__(self, sessionID, session):
        self.lock.acquire()
        try:
            #Add the new element
            self.entriesDict[sessionID] = session
            self.entriesList[self.lastIndex] = (sessionID, time.time())
            self.lastIndex = (self.lastIndex+1) % len(self.entriesList)

            #If the cache is full, we delete the oldest element to make an
            #empty space
            if self.lastIndex == self.firstIndex:
                del(self.entriesDict[self.entriesList[self.firstIndex][0]])
                self.firstIndex = (self.firstIndex+1) % len(self.entriesList)
        finally:
            self.lock.release()

    #Delete expired items
    def _purge(self):
        currentTime = time.time()

        #Search through the circular list, deleting expired elements until
        #we reach a non-expired element.  Since elements in list are
        #ordered in time, we can break once we reach the first non-expired
        #element
        index = self.firstIndex
        while index != self.lastIndex:
            if currentTime - self.entriesList[index][1] > self.maxAge:
                del(self.entriesDict[self.entriesList[index][0]])
                index = (index+1) % len(self.entriesList)
            else:
                break
        self.firstIndex = index

def _test():
    import doctest, SessionCache
    return doctest.testmod(SessionCache)

if __name__ == "__main__":
    _test()