示例#1
0
    def addStamp(self, stampclass, keys, passkey=None, **kwargs):
        """Adds a stamp of type `class` to the current envelope."""

        if passkey is not None:
            keys.unlock(passkey)
        signature = keys.signstring(self.payload.text())

        # Generate the full stamp obj we will insert.
        fullstamp = {}
        fullstamp['class'] = stampclass
        fullstamp['keyformat'] = keys.keydetails['format']
        fullstamp['pubkey'] = keys.pubkey
        fullstamp['signature'] = signature
        fullstamp['time_added'] = TavernUtils.inttime()

        # Copy in any passed values
        for key in kwargs.keys():
            # Remove the kwargs we know we already added
            if key not in ["stampclass", "keys", "passkey"]:
                fullstamp[key] = kwargs[key]

        proof = {}
        proof['class'] = 'sha256'
        proof['difficulty'] = self.server.serversettings.settings[
            'proof-of-work-difficulty']
        proof['proof'] = TavernUtils.proveWork(self.payload.hash(),
                                               proof['difficulty'])
        fullstamp['proof-of-work'] = proof

        self.dict['envelope']['stamps'].append(fullstamp)
示例#2
0
    def addStamp(self, stampclass, keys, passkey=None, **kwargs):
        """Adds a stamp of type `class` to the current envelope."""

        if passkey is not None:
            keys.unlock(passkey)
        signature = keys.signstring(self.payload.text())

        # Generate the full stamp obj we will insert.
        fullstamp = {}
        fullstamp['class'] = stampclass
        fullstamp['keyformat'] = keys.keydetails['format']
        fullstamp['pubkey'] = keys.pubkey
        fullstamp['signature'] = signature
        fullstamp['time_added'] = TavernUtils.inttime()

        # Copy in any passed values
        for key in kwargs.keys():
            # Remove the kwargs we know we already added
            if key not in ["stampclass", "keys", "passkey"]:
                fullstamp[key] = kwargs[key]

        proof = {}
        proof['class'] = 'sha256'
        proof[
            'difficulty'] = self.server.serversettings.settings[
            'proof-of-work-difficulty']
        proof['proof'] = TavernUtils.proveWork(
            self.payload.hash(),
            proof['difficulty'])
        fullstamp['proof-of-work'] = proof

        self.dict['envelope']['stamps'].append(fullstamp)
示例#3
0
    def generate(self,
                 password=None,
                 passkey=None,
                 random=False,
                 autoexpire=False):
        """Generate a new set of keys.

        Store only the encrypted version

        """

        if password is None and passkey is None and random is False:
            raise Exception(
                'KeyError',
                'Invalid call to generate() - Must include a password, passkey, or Random'
            )

        if random is True:
            password = TavernUtils.randstr(100)
            ret = password
        else:
            ret = None

        super().generate(autoexpire=autoexpire)
        if self.passkey is None and passkey is not None:
            self.passkey = passkey

        if self.passkey is None and password is not None:
            self.passkey = self.get_passkey(password=password)

        self.lock(passkey=self.passkey)
        return ret
示例#4
0
    def generate(self, password=None,
                 passkey=None, random=False, autoexpire=False):
        """Generate a new set of keys.

        Store only the encrypted version

        """

        if password is None and passkey is None and random is False:
            raise Exception(
                'KeyError',
                'Invalid call to generate() - Must include a password, passkey, or Random')

        if random is True:
            password = TavernUtils.randstr(100)
            ret = password
        else:
            ret = None

        super().generate(autoexpire=autoexpire)
        if self.passkey is None and passkey is not None:
            self.passkey = passkey

        if self.passkey is None and password is not None:
            self.passkey = self.get_passkey(password=password)

        self.lock(passkey=self.passkey)
        return ret
示例#5
0
    def messages(self, topic, maxposts, before=None):
        """Get all messages in a topic, no later than `before`"""
        if topic != 'all':
            if isinstance(topic, str):
                topics = []
                topics.append(server.sorttopic(topic))
            elif isinstance(topic, list):
                topics = []
                for t in topic:
                    topics.append(server.sorttopic(t))
            sorttopic = {'envelope.local.sorttopic': {'$in': topics}}
        else:
            sorttopic = {'envelope.local.sorttopic': {'$exists': True}}

        # Don't do this in the def, so that our cache is respected.
        if before is None:
            before = TavernUtils.inttime()

        # Append our search topic query.
        subjects = []
        search = {'envelope.payload.class': 'message',
                  'envelope.payload.regarding': {'$exists': False},
                  'envelope.local.time_added': {'$lt': before}}
        search.update(sorttopic)
        for envelope in server.db.unsafe.find('envelopes', search, limit=maxposts, sortkey='envelope.local.time_added', sortdirection='descending'):
            e = Envelope()
            e.loaddict(envelope)
            subjects.append(e)

        return subjects
示例#6
0
    def getbackdate(self, topic, maxposts, after):
        """Get the earliest dated message, before `after`"""
        sorttopic = server.sorttopic(topic)
        subjects = []
        if topic != "all":
            for envelope in server.db.unsafe.find('envelopes', {'envelope.local.sorttopic': sorttopic, 'envelope.payload.class': 'message', 'envelope.payload.regarding': {'$exists': False}, 'envelope.local.time_added': {'$gt': after}}, limit=maxposts + 1, sortkey='envelope.local.time_added', sortdirection='ascending'):
                subjects.append(envelope)
        else:
            for envelope in server.db.unsafe.find('envelopes', {'envelope.payload.class': 'message', 'envelope.payload.regarding': {'$exists': False}, 'envelope.local.time_added': {'$gt': after}}, limit=maxposts + 1, sortkey='envelope.local.time_added', sortdirection='ascending'):
                subjects.append(envelope)

        # Adding 1 to maxposts above, because we're going to use this to get the 10 posts AFTER the date we return from this function.
        # This is also the reason why, if we don't have maxposts posts, we
        # subtract 1 below. This ensures that we get ALL the posts in the
        # range.
        if len(subjects) > 0:
            if len(subjects) <= maxposts:
                ret = subjects[-1]['envelope']['local']['time_added'] + 1
                print("ret")
            else:
                ret = subjects[-1]['envelope']['local']['time_added']
        else:
            ret = TavernUtils.inttime()

        return ret
示例#7
0
    def encrypt_file(self, newfile):
        """Encrypt a string, to the gpg key of the specified recipient)"""

        # In order for this to work, we need to temporarily import B's key into A's keyring.
        # We then do the encryptions, and immediately remove it.
        recipient = Key(pub=encrypt_to)
        recipient._format_keys()
        self.gpg.import_keys(recipient.pubkey)

        tmpfilename = "tmp/gpgfiles/" + TavernUtils.longtime(
        ) + TavernUtils.randstr(50, printable=True)

        self.gpg.encrypt_file(stream=oldfile,
                              recipients=[recipient.fingerprint],
                              always_trust=True,
                              armor=True,
                              output=tmpfilename)
        self.gpg.delete_keys(recipient.fingerprint)
        return tmpfilename
示例#8
0
文件: key.py 项目: bitmonk/Tavern
    def encrypt_file(self, newfile):
        """Encrypt a string, to the gpg key of the specified recipient)"""

        # In order for this to work, we need to temporarily import B's key into A's keyring.
        # We then do the encryptions, and immediately remove it.
        recipient = Key(pub=encrypt_to)
        recipient._format_keys()
        self.gpg.import_keys(recipient.pubkey)

        tmpfilename = "tmp/gpgfiles/" + TavernUtils.longtime(
        ) + TavernUtils.randstr(50, printable=True)

        self.gpg.encrypt_file(
            stream=oldfile,
            recipients=[recipient.fingerprint],
            always_trust=True,
            armor=True,
            output=tmpfilename)
        self.gpg.delete_keys(recipient.fingerprint)
        return tmpfilename
示例#9
0
    def getvars(self, AllowGuestKey=True):
        """Retrieve the basic user variables out of your cookies."""
        self.user = User()
        # Load in our session token if we have one.
        userid = self.get_secure_cookie("tavern_settings")

        loaded = False
        if userid is not None:
            loaded = self.user.load_mongo_by_sha512(userid.decode('utf-8'))

        if loaded is False:
            # Either no cookie, or bad cookie. Either way, abort.
            self.clear_all_cookies()
            self.set_cookie("_xsrf", self.xsrf_token)
            self.user = User()

        # Get the passkey to unlock our privkey
        passkey = self.get_secure_cookie("tavern_passkey")
        if passkey is not None:
            self.user.passkey = passkey

        # Ensure our user has all expected fields
        # This method will also generate a key if necessary.
        if self.user.generate(AllowGuestKey=AllowGuestKey):
            self.setvars()

        # Check to see if we have support for datauris in our browser.
        # If we do, send the first ~10 pages with datauris.
        # After that switch back, since caching the images is likely to be
        # better, if you're a recurrent reader
        if not 'datauri' in self.user.UserSettings:
            if TavernUtils.randrange(1, 10) == 5:
                self.user.UserSettings['datauri'] = False
        if 'datauri' in self.user.UserSettings:
            self.user.datauri = self.user.UserSettings['datauri']
        elif self.browser[
                'ua_family'] == 'IE' and self.browser['ua_versions'][0] < 8:
            self.user.datauri = False
        elif self.browser[
                'ua_family'] == 'IE' and self.browser['ua_versions'][0] >= 8:
            self.user.datauri = True
        else:
            self.user.datauri = True
        if 'datauri' in self.request.arguments:
            if self.get_argument("datauri").lower() == 'true':
                self.user.datauri = True
            elif self.get_argument("datauri").lower() == 'false':
                self.user.datauri = False

        return self.user.UserSettings['username']
示例#10
0
    def getvars(self, AllowGuestKey=True):
        """Retrieve the basic user variables out of your cookies."""
        self.user = User()
        # Load in our session token if we have one.
        userid = self.get_secure_cookie("tavern_settings")

        loaded = False
        if userid is not None:
            loaded = self.user.load_mongo_by_sha512(userid.decode('utf-8'))

        if loaded is False:
            # Either no cookie, or bad cookie. Either way, abort.
            self.clear_all_cookies()
            self.set_cookie("_xsrf", self.xsrf_token)
            self.user = User()

        # Get the passkey to unlock our privkey
        passkey = self.get_secure_cookie("tavern_passkey")
        if passkey is not None:
            self.user.passkey = passkey

        # Ensure our user has all expected fields
        # This method will also generate a key if necessary.
        if self.user.generate(AllowGuestKey=AllowGuestKey):
            self.setvars()

        # Check to see if we have support for datauris in our browser.
        # If we do, send the first ~10 pages with datauris.
        # After that switch back, since caching the images is likely to be
        # better, if you're a recurrent reader
        if not 'datauri' in self.user.UserSettings:
            if TavernUtils.randrange(1, 10) == 5:
                self.user.UserSettings['datauri'] = False
        if 'datauri' in self.user.UserSettings:
            self.user.datauri = self.user.UserSettings['datauri']
        elif self.browser['ua_family'] == 'IE' and self.browser['ua_versions'][0] < 8:
            self.user.datauri = False
        elif self.browser['ua_family'] == 'IE' and self.browser['ua_versions'][0] >= 8:
            self.user.datauri = True
        else:
            self.user.datauri = True
        if 'datauri' in self.request.arguments:
            if self.get_argument("datauri").lower() == 'true':
                self.user.datauri = True
            elif self.get_argument("datauri").lower() == 'false':
                self.user.datauri = False

        return self.user.UserSettings['username']
示例#11
0
    def topicCount(self, topic, after=0, before=None, toponly=True):

        # Don't do this in the def, so that our cache is respected.
        if before is None:
            before = TavernUtils.inttime()

        sorttopic = server.sorttopic(topic)
        if toponly:
            count = server.db.unsafe.count(
                'envelopes',
                {'envelope.local.time_added': {'$lt': before},
                 'envelope.local.time_added': {'$gt': after},
                 'envelope.payload.regarding': {'$exists': False},
                 'envelope.local.sorttopic': sorttopic})
        else:
            count = server.db.unsafe.count(
                'envelopes',
                {'envelope.local.time_added': {'$lt': before},
                 'envelope.local.time_added': {'$gt': after},
                 'envelope.local.sorttopic': sorttopic})
        return count
示例#12
0
    def validate(self):
        """Ensures an envelope is valid, legal, and according to spec."""
        self.registerpayload()
        # Check headers
        if 'envelope' not in self.dict:
            self.server.logger.debug("Invalid Envelope. No Header")
            return False

        # Ensure we have 1 and only 1 author signature stamp
        stamps = self.dict['envelope']['stamps']
        foundauthor = 0
        for stamp in stamps:
            if stamp['class'] == "author":
                foundauthor += 1

        if foundauthor == 0:
            if self.dict['envelope']['payload']['class'] != 'privatemessage':
                self.server.logger.debug("No author stamp.")
                return False
        if foundauthor > 1:
            self.server.logger.debug("Too Many author stamps")
            return False

        # Ensure Every stamp validates.
        stamps = self.dict['envelope']['stamps']
        for stamp in stamps:

            if 'keyformat' not in stamp:
                self.server.logger.debug("Key format is not specififed.")
                return False

            if stamp['keyformat'] != 'gpg':
                self.server.logger.debug(
                    "Key not in acceptable container format.")
                return False

            # Retrieve the key, ensure it's valid.
            stampkey = Key(pub=stamp['pubkey'])
            if stampkey is None:
                self.server.logger.debug("Key is invalid.")
                return False

            if stampkey.keydetails['algorithm'] not in ['ElGamal', 'RSA', 'DSA']:
                self.server.logger.debug(
                    "Key does not use an acceptable algorithm.")
                return False

            if stampkey.keydetails['algorithm'] in ['ElGamal', 'RSA', 'DSA']:
                if int(stampkey.keydetails['length']) < 3072:
                    self.server.logger.debug("Key is too small.")
                    return False

            elif stampkey.keydetails['algorithm'] == 'ECDSA':
                if int(stampkey.keydetails['length']) < 233:
                    self.server.logger.debug("Key is too small.")
                    return False

            for uid in stampkey.keydetails['uids']:
                if uid not in [None, 'TAVERN', '']:
                    self.server.logger.debug(
                        "Key UID is potentially leaking information.")
                    return False

            # Ensure it matches the signature.
            if not stampkey.verify_string(stringtoverify=self.payload.text(), signature=stamp['signature']):
                self.server.logger.debug("Signature Failed to verify for stamp :: " +
                                         stamp['class'] + " :: " + stamp['pubkey'])
                return False

            # If they specify a proof-of-work in the stamp, make sure it's
            # valid.
            if 'proof-of-work' in stamp:
                    proof = stamp['proof-of-work']['proof']
                    difficulty = stamp['proof-of-work']['difficulty']
                    if stamp['proof-of-work']['class'] == 'sha256':
                        result = TavernUtils.checkWork(
                            self.payload.hash(),
                            proof,
                            difficulty)
                        if result is False:
                            self.server.logger.debug(
                                "Proof of work cannot be verified.")
                            return False
                    else:
                        self.server.logger.debug(
                            "Proof of work in unrecognized format. Ignoring.")

        # It's OK if they don't include a user-agent, but not if they include a
        # bad one.
        # if 'useragent' in self.dict['envelope']['payload']['author']:
        #     if not 'name' in self.dict['envelope']['payload']['author']['useragent']:
        #         self.server.logger.debug(
        #             "If you supply a user agent, it must have a valid name")
        #         return False
        #     if not isinstance(self.dict['envelope']['payload']['author']['useragent']['version'], int) and not isinstance(self.dict['envelope']['payload']['author']['useragent']['version'], float):
        #             self.server.logger.debug(
        #                 "Bad Useragent version must be a float or integer")
        #             return False

        # Do this last, so we don't waste time if the stamps are bad.
        if not self.payload.validate():
            self.server.logger.info("Payload does not validate.")
            return False

        return True
示例#13
0
    def validate(self):
        """Ensures an envelope is valid, legal, and according to spec."""
        self.registerpayload()
        # Check headers
        if 'envelope' not in self.dict:
            self.server.logger.debug("Invalid Envelope. No Header")
            return False

        # Ensure we have 1 and only 1 author signature stamp
        stamps = self.dict['envelope']['stamps']
        foundauthor = 0
        for stamp in stamps:
            if stamp['class'] == "author":
                foundauthor += 1

        if foundauthor == 0:
            if self.dict['envelope']['payload']['class'] != 'privatemessage':
                self.server.logger.debug("No author stamp.")
                return False
        if foundauthor > 1:
            self.server.logger.debug("Too Many author stamps")
            return False

        # Ensure Every stamp validates.
        stamps = self.dict['envelope']['stamps']
        for stamp in stamps:

            if 'keyformat' not in stamp:
                self.server.logger.debug("Key format is not specififed.")
                return False

            if stamp['keyformat'] != 'gpg':
                self.server.logger.debug(
                    "Key not in acceptable container format.")
                return False

            # Retrieve the key, ensure it's valid.
            stampkey = Key(pub=stamp['pubkey'])
            if stampkey is None:
                self.server.logger.debug("Key is invalid.")
                return False

            if stampkey.keydetails['algorithm'] not in [
                    'ElGamal', 'RSA', 'DSA'
            ]:
                self.server.logger.debug(
                    "Key does not use an acceptable algorithm.")
                return False

            if stampkey.keydetails['algorithm'] in ['ElGamal', 'RSA', 'DSA']:
                if int(stampkey.keydetails['length']) < 3072:
                    self.server.logger.debug("Key is too small.")
                    return False

            elif stampkey.keydetails['algorithm'] == 'ECDSA':
                if int(stampkey.keydetails['length']) < 233:
                    self.server.logger.debug("Key is too small.")
                    return False

            for uid in stampkey.keydetails['uids']:
                if uid not in [None, 'TAVERN', '']:
                    self.server.logger.debug(
                        "Key UID is potentially leaking information.")
                    return False

            # Ensure it matches the signature.
            if not stampkey.verify_string(stringtoverify=self.payload.text(),
                                          signature=stamp['signature']):
                self.server.logger.debug(
                    "Signature Failed to verify for stamp :: " +
                    stamp['class'] + " :: " + stamp['pubkey'])
                return False

            # If they specify a proof-of-work in the stamp, make sure it's
            # valid.
            if 'proof-of-work' in stamp:
                proof = stamp['proof-of-work']['proof']
                difficulty = stamp['proof-of-work']['difficulty']
                if stamp['proof-of-work']['class'] == 'sha256':
                    result = TavernUtils.checkWork(self.payload.hash(), proof,
                                                   difficulty)
                    if result is False:
                        self.server.logger.debug(
                            "Proof of work cannot be verified.")
                        return False
                else:
                    self.server.logger.debug(
                        "Proof of work in unrecognized format. Ignoring.")

        # It's OK if they don't include a user-agent, but not if they include a
        # bad one.
        # if 'useragent' in self.dict['envelope']['payload']['author']:
        #     if not 'name' in self.dict['envelope']['payload']['author']['useragent']:
        #         self.server.logger.debug(
        #             "If you supply a user agent, it must have a valid name")
        #         return False
        #     if not isinstance(self.dict['envelope']['payload']['author']['useragent']['version'], int) and not isinstance(self.dict['envelope']['payload']['author']['useragent']['version'], float):
        #             self.server.logger.debug(
        #                 "Bad Useragent version must be a float or integer")
        #             return False

        # Do this last, so we don't waste time if the stamps are bad.
        if not self.payload.validate():
            self.server.logger.info("Payload does not validate.")
            return False

        return True
示例#14
0
    def updateconfig(self):

        # Create a string/immutable version of ServerSettings that we can
        # compare against later to see if anything changed.
        tmpsettings = str(self.settings)

        if not 'hostname' in self.settings:
            self.settings['hostname'] = platform.node()

        if not 'web_url' in self.settings:
            self.settings['web_url'] = None

        if not 'downloadsurl' in self.settings:
            self.settings['downloadsurl'] = '/binaries/'

        # The Canonical URL is specified so that Google won't detect duplicate
        # content for every Tavern server, and penalize.
        if not 'canonical_url' in self.settings:
            self.settings['canonical_url'] = "https://tavern.is"

        if not 'logfile' in self.settings:
            self.settings[
                'logfile'] = "logs/" + self.settings['hostname'] + '.log'

        if not 'loglevel' in self.settings:
            self.settings[
                'loglevel'] = "INFO"

        if not 'mongo-hostname' in self.settings:
            self.settings['mongo-hostname'] = 'localhost'
        if not 'mongo-port' in self.settings:
            self.settings['mongo-port'] = 27017

        if not 'postgres-hostname' in self.settings:
            self.settings['postgres-hostname'] = 'localhost'
        if not 'postgres-user' in self.settings:
            self.settings['postgres-user'] = getpass.getuser()
        if not 'postgres-hostname' in self.settings:
            self.settings['postgres-hostname'] = "localhost"
        if not 'postgres-port' in self.settings:
            self.settings['postgres-port'] = 5432

        if not 'dbname' in self.settings:
            self.settings['dbname'] = 'Tavern'

        if not 'bin-mongo-hostname' in self.settings:
            self.settings['bin-mongo-hostname'] = 'localhost'
        if not 'bin-mongo-port' in self.settings:
            self.settings['bin-mongo-port'] = 27017
        if not 'bin-mongo-db' in self.settings:
            self.settings['bin-mongo-db'] = 'Tavern_Binaries'

        if not 'sessions-db-hostname' in self.settings:
            self.settings['sessions-db-hostname'] = 'localhost'
        if not 'sessions-db-port' in self.settings:
            self.settings['sessions-db-port'] = 27017
        if not 'sessions-db-name' in self.settings:
            self.settings['sessions-db-name'] = 'Tavern_Sessions'

        if not 'cache' in self.settings:
            self.settings['cache'] = {}

        if not 'user-trust' in self.settings['cache']:
            self.settings['cache']['user-trust'] = {}
            self.settings['cache']['user-trust']['seconds'] = 300
            self.settings['cache']['user-trust']['size'] = 10000

        if not 'message-ratings' in self.settings['cache']:
            self.settings['cache']['message-ratings'] = {}
            self.settings['cache']['message-ratings']['seconds'] = 300
            self.settings['cache']['message-ratings']['size'] = 10000

        if not 'avatarcache' in self.settings['cache']:
            self.settings['cache']['avatarcache'] = {}
            self.settings['cache']['avatarcache']['size'] = 100000
            self.settings['cache']['avatarcache']['seconds'] = None

        if not 'embedded' in self.settings['cache']:
            self.settings['cache']['embedded'] = {}
            self.settings['cache']['embedded']['size'] = 1000
            self.settings['cache']['embedded']['seconds'] = 3601

        if not 'user-note' in self.settings['cache']:
            self.settings['cache']['user-note'] = {}
            self.settings['cache']['user-note']['size'] = 10000
            self.settings['cache']['user-note']['seconds'] = 60

        if not 'subjects-in-topic' in self.settings['cache']:
            self.settings['cache']['subjects-in-topic'] = {}
            self.settings['cache']['subjects-in-topic']['size'] = 1000
            self.settings['cache']['subjects-in-topic']['seconds'] = 1

        if not 'toptopics' in self.settings['cache']:
            self.settings['cache']['toptopics'] = {}
            self.settings['cache']['toptopics']['size'] = 1
            self.settings['cache']['toptopics']['seconds'] = 3602

        # Settings related to the Web View
        if not 'templates' in self.settings['cache']:
            self.settings['cache']['templates'] = {}
            self.settings['cache']['templates']['size'] = 1000
            self.settings['cache']['templates']['seconds'] = 5

        if not 'getpagelemenent' in self.settings['cache']:
            self.settings['cache']['getpagelemenent'] = {}
            self.settings['cache']['getpagelemenent']['size'] = 1000
            self.settings['cache']['getpagelemenent']['seconds'] = 20

        if not 'message-page' in self.settings['cache']:
            self.settings['cache']['message-page'] = {}
            self.settings['cache']['message-page']['size'] = 1000
            self.settings['cache']['message-page']['seconds'] = 1

        if not 'topic-page' in self.settings['cache']:
            self.settings['cache']['topic-page'] = {}
            self.settings['cache']['topic-page']['size'] = 1000
            self.settings['cache']['topic-page']['seconds'] = 1

        if not 'uasparser' in self.settings['cache']:
            self.settings['cache']['uasparser'] = {}
            self.settings['cache']['uasparser']['size'] = 1000
            self.settings['cache']['uasparser']['seconds'] = 36001

        if not 'topiccount' in self.settings['cache']:
            self.settings['cache']['topiccount'] = {}
            self.settings['cache']['topiccount']['size'] = 1000
            self.settings['cache']['topiccount']['seconds'] = 10

        if not 'receiveEnvelope' in self.settings['cache']:
            self.settings['cache']['receiveEnvelope'] = {}
            self.settings['cache']['receiveEnvelope']['size'] = 10000
            self.settings['cache']['receiveEnvelope']['seconds'] = 1000

        if not 'getUsersPosts' in self.settings['cache']:
            self.settings['cache']['getUsersPosts'] = {}
            self.settings['cache']['getUsersPosts']['size'] = 10000
            self.settings['cache']['getUsersPosts']['seconds'] = 2

        if not 'sorttopic' in self.settings['cache']:
            self.settings['cache']['sorttopic'] = {}
            self.settings['cache']['sorttopic']['size'] = 1000000
            self.settings['cache']['sorttopic']['seconds'] = 10000000000

        if not 'formatText' in self.settings['cache']:
            self.settings['cache']['formatText'] = {}
            self.settings['cache']['formatText']['size'] = 1000
            self.settings['cache']['formatText']['seconds'] = 10000000000

        if not 'error_envelope' in self.settings['cache']:
            self.settings['cache']['error_envelope'] = {}
            self.settings['cache']['error_envelope']['size'] = 20
            self.settings['cache']['error_envelope']['seconds'] = 10000000000

        if not 'KeyGenerator' in self.settings:
            self.settings['KeyGenerator'] = {}
        if not 'num_pregens' in self.settings['KeyGenerator']:
            self.settings['KeyGenerator']['num_pregens'] = 5
        if not 'workers' in self.settings['KeyGenerator']:
            self.settings['KeyGenerator']['workers'] = 1

        if not 'keys' in self.settings:
            self.settings['keys'] = {}
        if not 'keysize' in self.settings['keys']:
            self.settings['keys']['keysize'] = 3072

        if not 'upload-dir' in self.settings:
            self.settings['upload-dir'] = '../nginx/uploads'

        if not 'mark-origin' in self.settings:
            self.settings['mark-origin'] = False

        if not 'mark-seen' in self.settings:
            self.settings['mark-seen'] = False

        if not 'max-upload-preview-size' in self.settings:
            self.settings['max-upload-preview-size'] = 10485760

        if not 'cookie-encryption' in self.settings:
            self.settings['cookie-encryption'] = TavernUtils.randstr(255)
        if not 'serverkey-password' in self.settings:
            self.settings[
                'serverkey-password'] = TavernUtils.randstr(255)
        if not 'embedserver' in self.settings:
            self.settings['embedserver'] = 'http://embed.is'

        if not 'maxembeddedurls' in self.settings:
            self.settings['maxembeddedurls'] = 10

        if not 'mongo-connections' in self.settings:
            self.settings['mongo-connections'] = 10

        if not 'dbtype' in self.settings:
            self.settings['dbtype'] = 'mongo'

        if not 'proof-of-work-difficulty' in self.settings:
            self.settings['proof-of-work-difficulty'] = 19

        # Report back on if there were any changes.
        if str(self.settings) == tmpsettings:
            return False
        else:
            return True
示例#15
0
文件: key.py 项目: bitmonk/Tavern
    def decrypt_file(self, tmpfile):

        tmpfilename = "tmp/gpgfiles/" + TavernUtils.longtime(
        ) + TavernUtils.randstr(50, printable=True)
        self.gpg.decrypt_file(tmpfile, output=tmpfilename)
        return tmpfilename
示例#16
0
    def decrypt_file(self, tmpfile):

        tmpfilename = "tmp/gpgfiles/" + TavernUtils.longtime(
        ) + TavernUtils.randstr(50, printable=True)
        self.gpg.decrypt_file(tmpfile, output=tmpfilename)
        return tmpfilename
示例#17
0
文件: Server.py 项目: bitmonk/Tavern
    def __init__(self, settingsfile=None, workingdir=None, slot='default'):

        super().__init__(slot)

        # Don't run this more than once.
        if self.__dict__.get('set') is True:
            return
        else:
            self.set = True

        self.logger = logging.getLogger('Tavern')

        # Should the server run in debug mode
        self.debug = False

        self.serversettings = ServerSettings.ServerSettings(settingsfile)
        if self.serversettings.updateconfig():
            self.serversettings.saveconfig()

        if not 'pubkey' in self.serversettings.settings or not 'privkey' in self.serversettings.settings:
            # Generate New config
            self.logger.info("Generating new Config")
            self.ServerKeys = Key()
            self.ServerKeys.generate()

            # We can't encrypt this.. We'd need to store the key here on the machine...
            # If you're worried about it, encrypt the disk, or use a loopback.
            self.serversettings.settings['pubkey'] = self.ServerKeys.pubkey
            self.serversettings.settings['privkey'] = self.ServerKeys.privkey

            self.serversettings.updateconfig()
            self.serversettings.saveconfig()

        self.mc = OrderedDict
        self.unusedkeycache = multiprocessing.Queue(
            self.serversettings.settings['KeyGenerator']['num_pregens'])
        # Break out the settings into it's own file, so we can include it without including all of server
        # This does cause a few shenanigans while loading here, but hopefully
        # it's minimal

        self.ServerKeys = Key(pub=self.serversettings.settings['pubkey'],
                              priv=self.serversettings.settings['privkey'])

        self.db = DBWrapper(
            name=self.serversettings.settings['dbname'],
            dbtype=self.serversettings.settings['dbtype'],
            host=self.serversettings.settings['mongo-hostname'],
            port=self.serversettings.settings['mongo-port'])
        self.sessions = DBWrapper(
            name=self.serversettings.settings['sessions-db-name'],
            dbtype=self.serversettings.settings['dbtype'],
            host=self.serversettings.settings['sessions-db-hostname'],
            port=self.serversettings.settings['sessions-db-port'])
        self.binaries = DBWrapper(
            name=self.serversettings.settings['bin-mongo-db'],
            dbtype='mongo',
            host=self.serversettings.settings['bin-mongo-hostname'],
            port=self.serversettings.settings['bin-mongo-port'])
        self.bin_GridFS = GridFS(self.binaries.unsafe.mongo)

        # Ensure we have Proper indexes.
        self.db.safe.ensure_index('envelope', 'envelope.local.time_added')
        self.db.safe.ensure_index('envelope', 'envelope.local.sorttopic')
        self.db.safe.ensure_index('envelope', 'envelope.local.payload_sha512')
        self.db.safe.ensure_index('envelope', 'envelope.payload.class')
        self.db.safe.ensure_index('envelope', 'envelope.payload.regarding')
        self.db.safe.ensure_index(
            'envelope',
            'envelope.payload.binaries.sha_512')
        self.db.safe.ensure_index('envelope', 'envelope.local.payload_sha512')
        self.db.safe.ensure_index('envelope', 'envelope.payload.author.pubkey')
        self.db.safe.ensure_index('envelope', 'envelope.payload.author.pubkey')
        self.db.safe.ensure_index('envelope', 'usertrusts.asking')
        self.db.safe.ensure_index('envelope', 'incomingtrust')

        self.binaries.safe.ensure_index('fs.files', 'filename')
        self.binaries.safe.ensure_index('fs.files', 'uploadDate')
        self.binaries.safe.ensure_index('fs.files', '_id')
        self.binaries.safe.ensure_index('fs.files', 'uploadDate')

        # Get a list of all the valid templates that can be used, to compare
        # against later on.
        self.availablethemes = []
        for name in os.listdir('themes'):
            if os.path.isdir(os.path.join('themes', name)):
                if name[:1] != ".":
                    self.availablethemes.append(name)

        self.serversettings.settings['static-revision'] = int(time.time())

        self.fortune = TavernUtils.randomWords(fortunefile="data/fortunes")
        self.wordlist = TavernUtils.randomWords(fortunefile="data/wordlist")

        # Define out logging options.
        formatter = logging.Formatter('[%(levelname)s] %(message)s')
        self.consolehandler = logging.StreamHandler()
        self.consolehandler.setFormatter(formatter)
        self.handler_file = logging.FileHandler(
            filename=self.serversettings.settings['logfile'])
        self.handler_file.setFormatter(formatter)

        self.logger.setLevel(self.serversettings.settings['loglevel'])
        level = self.serversettings.settings['loglevel']

        # Cache our JS, so we can include it later.
        file = open("static/scripts/instance.min.js")
        self.logger.info("Cached JS")
        TavernCache.cache['instance.js'] = file.read()
        file.close()
        self.guestacct = None
示例#18
0
    def updateconfig(self):

        # Create a string/immutable version of ServerSettings that we can
        # compare against later to see if anything changed.
        tmpsettings = str(self.settings)

        if not 'hostname' in self.settings:
            self.settings['hostname'] = platform.node()

        if not 'web_url' in self.settings:
            self.settings['web_url'] = None

        if not 'downloadsurl' in self.settings:
            self.settings['downloadsurl'] = '/binaries/'

        # The Canonical URL is specified so that Google won't detect duplicate
        # content for every Tavern server, and penalize.
        if not 'canonical_url' in self.settings:
            self.settings['canonical_url'] = "https://tavern.is"

        if not 'logfile' in self.settings:
            self.settings[
                'logfile'] = "logs/" + self.settings['hostname'] + '.log'

        if not 'loglevel' in self.settings:
            self.settings['loglevel'] = "INFO"

        if not 'mongo-hostname' in self.settings:
            self.settings['mongo-hostname'] = 'localhost'
        if not 'mongo-port' in self.settings:
            self.settings['mongo-port'] = 27017

        if not 'postgres-hostname' in self.settings:
            self.settings['postgres-hostname'] = 'localhost'
        if not 'postgres-user' in self.settings:
            self.settings['postgres-user'] = getpass.getuser()
        if not 'postgres-hostname' in self.settings:
            self.settings['postgres-hostname'] = "localhost"
        if not 'postgres-port' in self.settings:
            self.settings['postgres-port'] = 5432

        if not 'dbname' in self.settings:
            self.settings['dbname'] = 'Tavern'

        if not 'bin-mongo-hostname' in self.settings:
            self.settings['bin-mongo-hostname'] = 'localhost'
        if not 'bin-mongo-port' in self.settings:
            self.settings['bin-mongo-port'] = 27017
        if not 'bin-mongo-db' in self.settings:
            self.settings['bin-mongo-db'] = 'Tavern_Binaries'

        if not 'sessions-db-hostname' in self.settings:
            self.settings['sessions-db-hostname'] = 'localhost'
        if not 'sessions-db-port' in self.settings:
            self.settings['sessions-db-port'] = 27017
        if not 'sessions-db-name' in self.settings:
            self.settings['sessions-db-name'] = 'Tavern_Sessions'

        if not 'cache' in self.settings:
            self.settings['cache'] = {}

        if not 'user-trust' in self.settings['cache']:
            self.settings['cache']['user-trust'] = {}
            self.settings['cache']['user-trust']['seconds'] = 300
            self.settings['cache']['user-trust']['size'] = 10000

        if not 'message-ratings' in self.settings['cache']:
            self.settings['cache']['message-ratings'] = {}
            self.settings['cache']['message-ratings']['seconds'] = 300
            self.settings['cache']['message-ratings']['size'] = 10000

        if not 'avatarcache' in self.settings['cache']:
            self.settings['cache']['avatarcache'] = {}
            self.settings['cache']['avatarcache']['size'] = 100000
            self.settings['cache']['avatarcache']['seconds'] = None

        if not 'embedded' in self.settings['cache']:
            self.settings['cache']['embedded'] = {}
            self.settings['cache']['embedded']['size'] = 1000
            self.settings['cache']['embedded']['seconds'] = 3601

        if not 'user-note' in self.settings['cache']:
            self.settings['cache']['user-note'] = {}
            self.settings['cache']['user-note']['size'] = 10000
            self.settings['cache']['user-note']['seconds'] = 60

        if not 'subjects-in-topic' in self.settings['cache']:
            self.settings['cache']['subjects-in-topic'] = {}
            self.settings['cache']['subjects-in-topic']['size'] = 1000
            self.settings['cache']['subjects-in-topic']['seconds'] = 1

        if not 'toptopics' in self.settings['cache']:
            self.settings['cache']['toptopics'] = {}
            self.settings['cache']['toptopics']['size'] = 1
            self.settings['cache']['toptopics']['seconds'] = 3602

        # Settings related to the Web View
        if not 'templates' in self.settings['cache']:
            self.settings['cache']['templates'] = {}
            self.settings['cache']['templates']['size'] = 1000
            self.settings['cache']['templates']['seconds'] = 5

        if not 'getpagelemenent' in self.settings['cache']:
            self.settings['cache']['getpagelemenent'] = {}
            self.settings['cache']['getpagelemenent']['size'] = 1000
            self.settings['cache']['getpagelemenent']['seconds'] = 20

        if not 'message-page' in self.settings['cache']:
            self.settings['cache']['message-page'] = {}
            self.settings['cache']['message-page']['size'] = 1000
            self.settings['cache']['message-page']['seconds'] = 1

        if not 'topic-page' in self.settings['cache']:
            self.settings['cache']['topic-page'] = {}
            self.settings['cache']['topic-page']['size'] = 1000
            self.settings['cache']['topic-page']['seconds'] = 1

        if not 'uasparser' in self.settings['cache']:
            self.settings['cache']['uasparser'] = {}
            self.settings['cache']['uasparser']['size'] = 1000
            self.settings['cache']['uasparser']['seconds'] = 36001

        if not 'topiccount' in self.settings['cache']:
            self.settings['cache']['topiccount'] = {}
            self.settings['cache']['topiccount']['size'] = 1000
            self.settings['cache']['topiccount']['seconds'] = 10

        if not 'receiveEnvelope' in self.settings['cache']:
            self.settings['cache']['receiveEnvelope'] = {}
            self.settings['cache']['receiveEnvelope']['size'] = 10000
            self.settings['cache']['receiveEnvelope']['seconds'] = 1000

        if not 'getUsersPosts' in self.settings['cache']:
            self.settings['cache']['getUsersPosts'] = {}
            self.settings['cache']['getUsersPosts']['size'] = 10000
            self.settings['cache']['getUsersPosts']['seconds'] = 2

        if not 'sorttopic' in self.settings['cache']:
            self.settings['cache']['sorttopic'] = {}
            self.settings['cache']['sorttopic']['size'] = 1000000
            self.settings['cache']['sorttopic']['seconds'] = 10000000000

        if not 'formatText' in self.settings['cache']:
            self.settings['cache']['formatText'] = {}
            self.settings['cache']['formatText']['size'] = 1000
            self.settings['cache']['formatText']['seconds'] = 10000000000

        if not 'error_envelope' in self.settings['cache']:
            self.settings['cache']['error_envelope'] = {}
            self.settings['cache']['error_envelope']['size'] = 20
            self.settings['cache']['error_envelope']['seconds'] = 10000000000

        if not 'KeyGenerator' in self.settings:
            self.settings['KeyGenerator'] = {}
        if not 'num_pregens' in self.settings['KeyGenerator']:
            self.settings['KeyGenerator']['num_pregens'] = 5
        if not 'workers' in self.settings['KeyGenerator']:
            self.settings['KeyGenerator']['workers'] = 1

        if not 'keys' in self.settings:
            self.settings['keys'] = {}
        if not 'keysize' in self.settings['keys']:
            self.settings['keys']['keysize'] = 3072

        if not 'upload-dir' in self.settings:
            self.settings['upload-dir'] = '../nginx/uploads'

        if not 'mark-origin' in self.settings:
            self.settings['mark-origin'] = False

        if not 'mark-seen' in self.settings:
            self.settings['mark-seen'] = False

        if not 'max-upload-preview-size' in self.settings:
            self.settings['max-upload-preview-size'] = 10485760

        if not 'cookie-encryption' in self.settings:
            self.settings['cookie-encryption'] = TavernUtils.randstr(255)
        if not 'serverkey-password' in self.settings:
            self.settings['serverkey-password'] = TavernUtils.randstr(255)
        if not 'embedserver' in self.settings:
            self.settings['embedserver'] = 'http://embed.is'

        if not 'maxembeddedurls' in self.settings:
            self.settings['maxembeddedurls'] = 10

        if not 'mongo-connections' in self.settings:
            self.settings['mongo-connections'] = 10

        if not 'dbtype' in self.settings:
            self.settings['dbtype'] = 'mongo'

        if not 'proof-of-work-difficulty' in self.settings:
            self.settings['proof-of-work-difficulty'] = 19

        # Report back on if there were any changes.
        if str(self.settings) == tmpsettings:
            return False
        else:
            return True
示例#19
0
    def __init__(self, settingsfile=None, workingdir=None, slot='default'):

        super().__init__(slot)

        # Don't run this more than once.
        if self.__dict__.get('set') is True:
            return
        else:
            self.set = True

        self.logger = logging.getLogger('Tavern')

        # Should the server run in debug mode
        self.debug = False

        self.serversettings = ServerSettings.ServerSettings(settingsfile)
        if self.serversettings.updateconfig():
            self.serversettings.saveconfig()

        if not 'pubkey' in self.serversettings.settings or not 'privkey' in self.serversettings.settings:
            # Generate New config
            self.logger.info("Generating new Config")
            self.ServerKeys = Key()
            self.ServerKeys.generate()

            # We can't encrypt this.. We'd need to store the key here on the machine...
            # If you're worried about it, encrypt the disk, or use a loopback.
            self.serversettings.settings['pubkey'] = self.ServerKeys.pubkey
            self.serversettings.settings['privkey'] = self.ServerKeys.privkey

            self.serversettings.updateconfig()
            self.serversettings.saveconfig()

        self.mc = OrderedDict
        self.unusedkeycache = multiprocessing.Queue(
            self.serversettings.settings['KeyGenerator']['num_pregens'])
        # Break out the settings into it's own file, so we can include it without including all of server
        # This does cause a few shenanigans while loading here, but hopefully
        # it's minimal

        self.ServerKeys = Key(pub=self.serversettings.settings['pubkey'],
                              priv=self.serversettings.settings['privkey'])

        self.db = DBWrapper(
            name=self.serversettings.settings['dbname'],
            dbtype=self.serversettings.settings['dbtype'],
            host=self.serversettings.settings['mongo-hostname'],
            port=self.serversettings.settings['mongo-port'])
        self.sessions = DBWrapper(
            name=self.serversettings.settings['sessions-db-name'],
            dbtype=self.serversettings.settings['dbtype'],
            host=self.serversettings.settings['sessions-db-hostname'],
            port=self.serversettings.settings['sessions-db-port'])
        self.binaries = DBWrapper(
            name=self.serversettings.settings['bin-mongo-db'],
            dbtype='mongo',
            host=self.serversettings.settings['bin-mongo-hostname'],
            port=self.serversettings.settings['bin-mongo-port'])
        self.bin_GridFS = GridFS(self.binaries.unsafe.mongo)

        # Ensure we have Proper indexes.
        self.db.safe.ensure_index('envelope', 'envelope.local.time_added')
        self.db.safe.ensure_index('envelope', 'envelope.local.sorttopic')
        self.db.safe.ensure_index('envelope', 'envelope.local.payload_sha512')
        self.db.safe.ensure_index('envelope', 'envelope.payload.class')
        self.db.safe.ensure_index('envelope', 'envelope.payload.regarding')
        self.db.safe.ensure_index('envelope',
                                  'envelope.payload.binaries.sha_512')
        self.db.safe.ensure_index('envelope', 'envelope.local.payload_sha512')
        self.db.safe.ensure_index('envelope', 'envelope.payload.author.pubkey')
        self.db.safe.ensure_index('envelope', 'envelope.payload.author.pubkey')
        self.db.safe.ensure_index('envelope', 'usertrusts.asking')
        self.db.safe.ensure_index('envelope', 'incomingtrust')

        self.binaries.safe.ensure_index('fs.files', 'filename')
        self.binaries.safe.ensure_index('fs.files', 'uploadDate')
        self.binaries.safe.ensure_index('fs.files', '_id')
        self.binaries.safe.ensure_index('fs.files', 'uploadDate')

        # Get a list of all the valid templates that can be used, to compare
        # against later on.
        self.availablethemes = []
        for name in os.listdir('themes'):
            if os.path.isdir(os.path.join('themes', name)):
                if name[:1] != ".":
                    self.availablethemes.append(name)

        self.serversettings.settings['static-revision'] = int(time.time())

        self.fortune = TavernUtils.randomWords(fortunefile="data/fortunes")
        self.wordlist = TavernUtils.randomWords(fortunefile="data/wordlist")

        # Define out logging options.
        formatter = logging.Formatter('[%(levelname)s] %(message)s')
        self.consolehandler = logging.StreamHandler()
        self.consolehandler.setFormatter(formatter)
        self.handler_file = logging.FileHandler(
            filename=self.serversettings.settings['logfile'])
        self.handler_file.setFormatter(formatter)

        self.logger.setLevel(self.serversettings.settings['loglevel'])
        level = self.serversettings.settings['loglevel']

        # Cache our JS, so we can include it later.
        file = open("static/scripts/instance.min.js")
        self.logger.info("Cached JS")
        TavernCache.cache['instance.js'] = file.read()
        file.close()
        self.guestacct = None