Example #1
0
    def __new__(cls,
                id=None,
                doc=None,
                spec=None,
                fields=None,
                upsert=False,
                **kwargs):
        from pritunl import utils
        fields = fields or cls.fields

        mongo_object = object.__new__(cls)
        mongo_object.changed = set()
        mongo_object.unseted = set()
        mongo_object.id = id
        mongo_object.loaded_fields = fields

        if id or doc or spec:
            mongo_object.exists = True
            try:
                mongo_object.load(doc=doc, spec=spec, fields=fields)
            except NotFound:
                if not upsert:
                    return None
                mongo_object.exists = False
                if not id:
                    mongo_object.id = database.ObjectId()
        else:
            mongo_object.exists = False
            mongo_object.id = database.ObjectId()
        return mongo_object
Example #2
0
def publish(channels, message, extra=None, transaction=None):
    if cache.has_cache:
        return cache.publish(channels, message, extra=extra)

    collection = mongo.get_collection('messages')
    doc = {
        'message': message,
        'timestamp': utils.now(),
    }

    if extra:
        for key, val in list(extra.items()):
            doc[key] = val

    # ObjectId must be set by server and ObjectId order must match $natural
    # order. Docs sent in order on client are not guaranteed to match $natural
    # order on server. Nonce is added to force an insert from upsert where
    # insert is not supported.
    # When using inserts manipulate=False must be set to prevent pymongo
    # from setting ObjectId locally.
    if transaction:
        tran_collection = transaction.collection(collection.name_str)

        if isinstance(channels, str):
            doc['channel'] = channels
            tran_collection.update({
                'nonce': database.ObjectId(),
            }, {
                '$set': doc,
            },
                                   upsert=True)
        else:
            for channel in channels:
                doc_copy = doc.copy()
                doc_copy['channel'] = channel

                tran_collection.bulk().find({
                    'nonce': database.ObjectId(),
                }).upsert().update({
                    '$set': doc_copy,
                })
            tran_collection.bulk_execute()
    else:
        if isinstance(channels, str):
            doc['channel'] = channels
            collection.insert(doc, manipulate=False)
        else:
            docs = []
            for channel in channels:
                doc_copy = doc.copy()
                doc_copy['channel'] = channel
                docs.append(doc_copy)
            collection.insert(docs, manipulate=False)
Example #3
0
def link_state_delete():
    if settings.app.demo_mode:
        return utils.demo_blocked()

    auth_token = flask.request.headers.get('Auth-Token', None)
    auth_timestamp = flask.request.headers.get('Auth-Timestamp', None)
    auth_nonce = flask.request.headers.get('Auth-Nonce', None)
    auth_signature = flask.request.headers.get('Auth-Signature', None)
    if not auth_token or not auth_timestamp or not auth_nonce or \
            not auth_signature:
        return flask.abort(406)
    auth_token = auth_token[:256]
    auth_timestamp = auth_timestamp[:64]
    auth_nonce = auth_nonce[:32]
    auth_signature = auth_signature[:512]

    try:
        if abs(int(auth_timestamp) - int(utils.time_now())) > \
                settings.app.auth_time_window:
            return flask.abort(408)
    except ValueError:
        return flask.abort(405)

    host = link.get_host(database.ObjectId(auth_token))
    if not host:
        return flask.abort(404)

    auth_string = '&'.join([
        auth_token,
        auth_timestamp,
        auth_nonce,
        flask.request.method,
        flask.request.path,
    ])

    if len(auth_string) > AUTH_SIG_STRING_MAX_LEN:
        return flask.abort(413)

    auth_test_signature = base64.b64encode(
        hmac.new(host.secret.encode(), auth_string.encode(),
                 hashlib.sha512).digest()).decode()
    if not utils.const_compare(auth_signature, auth_test_signature):
        return flask.abort(401)

    nonces_collection = mongo.get_collection('auth_nonces')
    try:
        nonces_collection.insert({
            'token': auth_token,
            'nonce': auth_nonce,
            'timestamp': utils.now(),
        })
    except pymongo.errors.DuplicateKeyError:
        return flask.abort(409)

    host.set_inactive()

    return utils.jsonify({})
Example #4
0
def json_object_hook_handler(obj):
    obj_data = obj.get('$obj')
    if obj_data:
        object_type, obj_data = obj_data
        if object_type == 'oid':
            return database.ObjectId(obj_data)
        elif object_type == 'date':
            return datetime.datetime.fromtimestamp(obj_data / 1000.,
                                                   bson.tz_util.utc)
    return obj
Example #5
0
    def __init__(self, priority=None, retry=None, **kwargs):
        mongo.MongoObject.__init__(self)
        self.ttl = settings.mongo.queue_ttl
        self.type = self.type
        self.reserve_id = self.reserve_id
        self.runner_id = database.ObjectId()
        self.claimed = False
        self.queue_com = QueueCom()
        self.keep_alive_thread = None

        if priority is not None:
            self.priority = priority
        if retry is not None:
            self.retry = retry
Example #6
0
    def __init__(self, lock_id=None, priority=None, ttl=None, **kwargs):
        mongo.MongoObject.__init__(self)
        self.ttl = settings.mongo.tran_ttl

        if lock_id is not None:
            self.lock_id = lock_id
        if self.lock_id is None:
            self.lock_id = database.ObjectId()

        if priority is not None:
            self.priority = priority

        if ttl is not None:
            self.ttl = ttl

        if self.actions:
            actions_json = zlib.decompress(self.actions)
            self.action_sets = json.loads(
                actions_json, object_hook=utils.json_object_hook_handler)
        else:
            self.action_sets = []
Example #7
0
def publish(channels, message, extra=None, cap=50, ttl=300):
    if isinstance(channels, str):
        channels = [channels]

    for channel in channels:
        doc = {
            '_id': database.ObjectId(),
            'message': message,
            'timestamp': utils.now(),
        }
        if extra:
            for key, val in list(extra.items()):
                doc[key] = val

        doc = json.dumps(doc, default=utils.json_default)

        pipe = _client.pipeline()
        pipe.lpush(channel, doc)
        pipe.ltrim(channel, 0, cap)
        if ttl:
            pipe.expire(channel, ttl)
        pipe.publish(channel, doc)
        pipe.execute()
Example #8
0
def link_state_put():
    if settings.app.demo_mode:
        return utils.demo_blocked()

    auth_token = flask.request.headers.get('Auth-Token', None)
    auth_timestamp = flask.request.headers.get('Auth-Timestamp', None)
    auth_nonce = flask.request.headers.get('Auth-Nonce', None)
    auth_signature = flask.request.headers.get('Auth-Signature', None)
    if not auth_token or not auth_timestamp or not auth_nonce or \
            not auth_signature:
        return flask.abort(406)
    auth_token = auth_token[:256]
    auth_timestamp = auth_timestamp[:64]
    auth_nonce = auth_nonce[:32]
    auth_signature = auth_signature[:512]

    try:
        if abs(int(auth_timestamp) - int(utils.time_now())) > \
                settings.app.auth_time_window:
            return flask.abort(408)
    except ValueError:
        return flask.abort(405)

    host = link.get_host(database.ObjectId(auth_token))
    if not host:
        return flask.abort(404)

    auth_string = '&'.join([
        auth_token,
        auth_timestamp,
        auth_nonce,
        flask.request.method,
        flask.request.path,
    ])

    if len(auth_string) > AUTH_SIG_STRING_MAX_LEN:
        return flask.abort(413)

    auth_test_signature = base64.b64encode(
        hmac.new(host.secret.encode(), auth_string.encode(),
                 hashlib.sha512).digest()).decode()
    if not utils.const_compare(auth_signature, auth_test_signature):
        return flask.abort(401)

    nonces_collection = mongo.get_collection('auth_nonces')
    try:
        nonces_collection.insert({
            'token': auth_token,
            'nonce': auth_nonce,
            'timestamp': utils.now(),
        })
    except pymongo.errors.DuplicateKeyError:
        return flask.abort(409)

    host.load_link()

    host.version = flask.request.json.get('version')
    host.public_address = flask.request.json.get('public_address')
    host.local_address = flask.request.json.get('local_address')
    host.address6 = flask.request.json.get('address6')
    if flask.request.json.get('hosts'):
        host.hosts = flask.request.json.get('hosts')
        if host.hosts_hist:
            host.hosts_hist.insert(0, flask.request.json.get('hosts'))
            host.hosts_hist = host.hosts_hist[:6]
        else:
            host.hosts_hist = [flask.request.json.get('hosts')]
    else:
        host.hosts = None
        host.hosts_hist = None

    state, active = host.get_state()
    if active:
        host.location.status = flask.request.json.get('status') or None
        host.location.commit('status')

    data = json.dumps(state, default=lambda x: str(x))
    data += (16 - len(data) % 16) * '\x00'

    iv = os.urandom(16)
    key = hashlib.sha256(host.secret.encode()).digest()
    cipher = Cipher(algorithms.AES(key),
                    modes.CBC(iv),
                    backend=default_backend()).encryptor()
    enc_data = base64.b64encode(
        cipher.update(data.encode()) + cipher.finalize())

    enc_signature = base64.b64encode(
        hmac.new(host.secret.encode(), enc_data,
                 hashlib.sha512).digest()).decode()

    resp = flask.Response(response=enc_data, mimetype='application/base64')
    resp.headers.add('Cache-Control', 'no-cache, no-store, must-revalidate')
    resp.headers.add('Pragma', 'no-cache')
    resp.headers.add('Expires', 0)
    resp.headers.add('Cipher-IV', base64.b64encode(iv))
    resp.headers.add('Cipher-Signature', enc_signature)

    return resp
Example #9
0
def json_opt_oid(key):
    val = flask.request.json.get(key)
    return None if val is None else database.ObjectId(val)
Example #10
0
def json_oid(key):
    return database.ObjectId(flask.request.json[key])
Example #11
0
 def __init__(self, run_id=None, **kwargs):
     mongo.MongoObject.__init__(self)
     self.type = self.type
     self.runner_id = database.ObjectId()