Beispiel #1
0
def user_linked_key_page_delete(short_code):
    utils.rand_sleep()

    collection = mongo.get_collection("users_key_link")
    collection.remove({"short_id": short_code})

    return utils.jsonify({})
Beispiel #2
0
def _find_doc(query, one_time=None, one_time_new=False):
    utils.rand_sleep()

    collection = mongo.get_collection("users_key_link")
    doc = collection.find_one(query)

    if one_time and doc and doc.get("one_time"):
        short_id = utils.generate_short_id()
        collection = mongo.get_collection("users_key_link")

        if one_time_new:
            set_doc = {"short_id": short_id}
        else:
            set_doc = {"one_time": "used"}

        response = collection.update(
            {"_id": doc["_id"], "short_id": doc["short_id"], "one_time": True}, {"$set": set_doc}
        )
        if not response["updatedExisting"]:
            return None

        if one_time_new:
            doc["short_id"] = short_id

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)

    return doc
Beispiel #3
0
def key_sync_get(org_id, user_id, server_id, key_hash):
    utils.rand_sleep()

    if not settings.local.sub_active:
        return utils.response('', status_code=480)

    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(401)
    auth_nonce = auth_nonce[:32]

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

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(404)

    user = org.get_user(id=user_id)
    if not user:
        return flask.abort(404)
    elif not user.sync_secret:
        return flask.abort(404)

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

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

    auth_test_signature = base64.b64encode(hmac.new(
        user.sync_secret.encode(), auth_string,
        hashlib.sha256).digest())
    if 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(),
        }, w=0)
    except pymongo.errors.DuplicateKeyError:
        return flask.abort(401)

    key_conf = user.sync_conf(server_id, key_hash)
    if key_conf:
        return utils.response(key_conf['conf'])
    return utils.response('')
Beispiel #4
0
def _find_doc(query, one_time=None, one_time_new=False):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one(query)

    if one_time and doc and doc.get('one_time'):
        short_id = utils.generate_short_id()
        collection = mongo.get_collection('users_key_link')

        if one_time_new:
            set_doc = {
                'short_id': short_id,
            }
        else:
            set_doc = {
                'one_time': 'used',
            }

        response = collection.update({
            '_id': doc['_id'],
            'short_id': doc['short_id'],
            'one_time': True,
        }, {'$set': set_doc})
        if not response['updatedExisting']:
            return None

        if one_time_new:
            doc['short_id'] = short_id

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)

    return doc
Beispiel #5
0
def key_sync_get(org_id, user_id, server_id, key_hash):
    utils.rand_sleep()

    if not settings.local.sub_active:
        return utils.response('', status_code=480)

    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(401)
    auth_nonce = auth_nonce[:32]

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

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(401)

    user = org.get_user(id=user_id)
    if not user:
        return flask.abort(401)
    elif not user.sync_secret:
        return flask.abort(401)

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

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

    auth_test_signature = base64.b64encode(hmac.new(
        user.sync_secret.encode(), auth_string,
        hashlib.sha256).digest())
    if 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(),
        }, w=0)
    except pymongo.errors.DuplicateKeyError:
        return flask.abort(401)

    key_conf = user.sync_conf(server_id, key_hash)
    if key_conf:
        return utils.response(key_conf['conf'])
    return utils.response('')
Beispiel #6
0
def _find_doc(query, one_time=None, one_time_new=False):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one(query)

    if one_time and doc and doc.get('one_time'):
        short_id = utils.generate_short_id()
        collection = mongo.get_collection('users_key_link')

        if one_time_new:
            set_doc = {
                'short_id': short_id,
            }
        else:
            set_doc = {
                'one_time': 'used',
            }

        response = collection.update({
            '_id': doc['_id'],
            'short_id': doc['short_id'],
            'one_time': True,
        }, {'$set': set_doc})
        if not response['updatedExisting']:
            return None

        if one_time_new:
            doc['short_id'] = short_id

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)

    return doc
Beispiel #7
0
def user_linked_key_page_delete_get(short_id):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    collection.remove({
        'short_id': short_id,
    })
    return utils.jsonify({})
Beispiel #8
0
def user_linked_key_page_delete_get(short_code):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    collection.remove({
        'short_id': short_code,
    })
    return utils.jsonify({})
Beispiel #9
0
def user_linked_key_page_get(short_code):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'short_id': short_code,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    org = organization.get_by_id(doc['org_id'])
    user = org.get_user(id=doc['user_id'])

    if settings.local.sub_active and settings.app.theme == 'dark':
        view_name = KEY_VIEW_DARK_NAME
    else:
        view_name = KEY_VIEW_NAME

    key_page = static.StaticFile(settings.conf.www_path,
                                 view_name,
                                 cache=False).data
    key_page = key_page.replace('<%= user_name %>',
                                '%s - %s' % (org.name, user.name))
    key_page = key_page.replace('<%= user_key_url %>',
                                '/key/%s.tar' % (doc['key_id']))

    if org.otp_auth:
        key_page = key_page.replace('<%= user_otp_key %>', user.otp_secret)
        key_page = key_page.replace(
            '<%= user_otp_url %>', 'otpauth://totp/%s@%s?secret=%s' %
            (user.name, org.name, user.otp_secret))
    else:
        key_page = key_page.replace('<%= user_otp_key %>', '')
        key_page = key_page.replace('<%= user_otp_url %>', '')

    key_page = key_page.replace('<%= short_id %>', doc['short_id'])

    conf_links = ''

    if settings.local.sub_active and settings.local.sub_plan == 'enterprise':
        conf_links += '<a class="btn btn-success" ' + \
            'style="margin-top: 7px;" ' + \
            'title="Download Chromebook Keys" ' + \
            'href="/key_onc/%s.zip">Download Chromebook Keys</a><br>\n' % (
                doc['key_id'])

    for server in org.iter_servers():
        conf_links += '<a class="btn btn-sm" title="Download Key" ' + \
            'href="/key/%s/%s.key">Download Key (%s)</a><br>\n' % (
                doc['key_id'], server.id, server.name)
    key_page = key_page.replace('<%= conf_links %>', conf_links)

    return key_page
Beispiel #10
0
def user_linked_key_page_get(short_code):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'short_id': short_code,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    org = organization.get_by_id(doc['org_id'])
    user = org.get_user(id=doc['user_id'])

    if settings.local.sub_active and settings.app.theme == 'dark':
        view_name = KEY_VIEW_DARK_NAME
    else:
        view_name = KEY_VIEW_NAME

    key_page = static.StaticFile(settings.conf.www_path, view_name,
        cache=False).data
    key_page = key_page.replace('<%= user_name %>', '%s - %s' % (
        org.name, user.name))
    key_page = key_page.replace('<%= user_key_url %>', '/key/%s.tar' % (
        doc['key_id']))

    if org.otp_auth:
        key_page = key_page.replace('<%= user_otp_key %>', user.otp_secret)
        key_page = key_page.replace('<%= user_otp_url %>',
            'otpauth://totp/%s@%s?secret=%s' % (
                user.name, org.name, user.otp_secret))
    else:
        key_page = key_page.replace('<%= user_otp_key %>', '')
        key_page = key_page.replace('<%= user_otp_url %>', '')

    key_page = key_page.replace('<%= short_id %>', doc['short_id'])

    conf_links = ''

    if settings.local.sub_active and settings.local.sub_plan == 'enterprise':
        conf_links += '<a class="btn btn-success" ' + \
            'style="margin-top: 7px;" ' + \
            'title="Download Chromebook Keys" ' + \
            'href="/key_onc/%s.zip">Download Chromebook Keys</a><br>\n' % (
                doc['key_id'])

    for server in org.iter_servers():
        conf_links += '<a class="btn btn-sm" title="Download Key" ' + \
            'href="/key/%s/%s.key">Download Key (%s)</a><br>\n' % (
                doc['key_id'], server.id, server.name)
    key_page = key_page.replace('<%= conf_links %>', conf_links)

    return key_page
Beispiel #11
0
def setup_mongodb_put():
    global setup_state

    setup_key = flask.request.json['setup_key']
    mongodb_uri = flask.request.json['mongodb_uri']

    if setup_state != 'setup':
        return flask.abort(404)

    utils.rand_sleep()
    if setup_key != settings.local.setup_key:
        return utils.jsonify(
            {
                'error': SETUP_KEY_INVALID,
                'error_msg': SETUP_KEY_INVALID_MSG,
            }, 400)

    if not mongodb_uri:
        return utils.jsonify(
            {
                'error': MONGODB_URI_INVALID,
                'error_msg': MONGODB_URI_INVALID_MSG,
            }, 400)

    try:
        client = pymongo.MongoClient(mongodb_uri,
                                     connectTimeoutMS=MONGO_CONNECT_TIMEOUT)
        database = client.get_default_database()
    except pymongo.errors.ConfigurationError as error:
        if 'auth failed' in str(error):
            return utils.jsonify(
                {
                    'error': MONGODB_AUTH_ERROR,
                    'error_msg': MONGODB_AUTH_ERROR_MSG,
                }, 400)
        raise
    except pymongo.errors.ConnectionFailure:
        return utils.jsonify(
            {
                'error': MONGODB_CONNECT_ERROR,
                'error_msg': MONGODB_CONNECT_ERROR_MSG,
            }, 400)

    settings.conf.mongodb_uri = mongodb_uri
    settings.conf.commit()

    db_ver_int = utils.get_db_ver_int()
    if check_db_ver(db_ver_int):
        setup_state = 'upgrade'
        upgrade_database()
    else:
        stop_server()

    return ''
Beispiel #12
0
def user_linked_key_archive_get(key_id):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'key_id': key_id,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    return _get_key_archive(doc['org_id'], doc['user_id'])
Beispiel #13
0
def user_linked_key_archive_get(key_id):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'key_id': key_id,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    return _get_key_archive(doc['org_id'], doc['user_id'])
Beispiel #14
0
def setup_mongodb_put():
    global setup_state

    setup_key = flask.request.json['setup_key']
    mongodb_uri = flask.request.json['mongodb_uri']

    if setup_state != 'setup':
        return flask.abort(404)

    utils.rand_sleep()
    if setup_key != settings.local.setup_key:
        return utils.jsonify({
            'error': SETUP_KEY_INVALID,
            'error_msg': SETUP_KEY_INVALID_MSG,
        }, 400)

    if not mongodb_uri:
        return utils.jsonify({
            'error': MONGODB_URI_INVALID,
            'error_msg': MONGODB_URI_INVALID_MSG,
        }, 400)

    try:
        client = pymongo.MongoClient(mongodb_uri,
            connectTimeoutMS=MONGO_CONNECT_TIMEOUT)
        database = client.get_default_database()
    except pymongo.errors.ConfigurationError as error:
        if 'auth failed' in str(error):
            return utils.jsonify({
                'error': MONGODB_AUTH_ERROR,
                'error_msg': MONGODB_AUTH_ERROR_MSG,
            }, 400)
        raise
    except pymongo.errors.ConnectionFailure:
        return utils.jsonify({
            'error': MONGODB_CONNECT_ERROR,
            'error_msg': MONGODB_CONNECT_ERROR_MSG,
        }, 400)

    settings.conf.mongodb_uri = mongodb_uri
    settings.conf.commit()

    db_ver_int = utils.get_db_ver_int()
    if check_db_ver(db_ver_int):
        setup_state = 'upgrade'
        upgrade_database()
    else:
        stop_server()

    return ''
Beispiel #15
0
def user_linked_key_page_delete(short_code):
    utils.rand_sleep()
    remote_addr = utils.get_remote_addr()

    journal.entry(
        journal.USER_PROFILE_DELETE,
        remote_address=remote_addr,
        event_long='Temporary profile link deleted',
    )

    collection = mongo.get_collection('users_key_link')
    collection.remove({
        'short_id': short_code,
    })

    return utils.jsonify({})
Beispiel #16
0
def user_linked_key_page_delete(short_code):
    utils.rand_sleep()
    remote_addr = utils.get_remote_addr()

    journal.entry(
        journal.USER_PROFILE_DELETE,
        remote_address=remote_addr,
        event_long='Temporary profile link deleted',
    )

    collection = mongo.get_collection('users_key_link')
    collection.remove({
        'short_id': short_code,
    })

    return utils.jsonify({})
Beispiel #17
0
def user_linked_key_page_get(short_id):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'short_id': short_id,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    org = organization.get_by_id(doc['org_id'])
    user = org.get_user(id=doc['user_id'])

    key_page = static.StaticFile(settings.conf.www_path,
                                 KEY_VIEW_NAME,
                                 cache=False).data
    key_page = key_page.replace('<%= user_name %>',
                                '%s - %s' % (org.name, user.name))
    key_page = key_page.replace('<%= user_key_url %>',
                                '/key/%s.tar' % (doc['key_id']))

    if org.otp_auth:
        key_page = key_page.replace('<%= user_otp_key %>', user.otp_secret)
        key_page = key_page.replace(
            '<%= user_otp_url %>', 'otpauth://totp/%s@%s?secret=%s' %
            (user.name, org.name, user.otp_secret))
    else:
        key_page = key_page.replace('<%= user_otp_key %>', '')
        key_page = key_page.replace('<%= user_otp_url %>', '')

    key_page = key_page.replace('<%= short_id %>', doc['short_id'])

    conf_links = ''
    for server in org.iter_servers():
        conf_links += '<a class="btn btn-sm" title="Download Key" ' + \
            'href="/key/%s/%s.key">Download Key (%s)</a><br>\n' % (
                doc['key_id'], server.id, server.name)
    key_page = key_page.replace('<%= conf_links %>', conf_links)

    return key_page
Beispiel #18
0
def user_linked_key_page_get(short_id):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'short_id': short_id,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    org = organization.get_by_id(doc['org_id'])
    user = org.get_user(id=doc['user_id'])

    key_page = static.StaticFile(settings.conf.www_path, KEY_VIEW_NAME,
        cache=False).data
    key_page = key_page.replace('<%= user_name %>', '%s - %s' % (
        org.name, user.name))
    key_page = key_page.replace('<%= user_key_url %>', '/key/%s.tar' % (
        doc['key_id']))

    if org.otp_auth:
        key_page = key_page.replace('<%= user_otp_key %>', user.otp_secret)
        key_page = key_page.replace('<%= user_otp_url %>',
            'otpauth://totp/%s@%s?secret=%s' % (
                user.name, org.name, user.otp_secret))
    else:
        key_page = key_page.replace('<%= user_otp_key %>', '')
        key_page = key_page.replace('<%= user_otp_url %>', '')

    key_page = key_page.replace('<%= short_id %>', doc['short_id'])

    conf_links = ''
    for server in org.iter_servers():
        conf_links += '<a class="btn btn-sm" title="Download Key" ' + \
            'href="/key/%s/%s.key">Download Key (%s)</a><br>\n' % (
                doc['key_id'], server.id, server.name)
    key_page = key_page.replace('<%= conf_links %>', conf_links)

    return key_page
Beispiel #19
0
def user_uri_key_page_get(short_code):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'short_id': short_code,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    org = organization.get_by_id(doc['org_id'])
    user = org.get_user(id=doc['user_id'])

    keys = {}
    for server in org.iter_servers():
        key = user.build_key_conf(server.id)
        keys[key['name']] = key['conf']

    return utils.jsonify(keys)
Beispiel #20
0
def key_sync_get(org_id, user_id, server_id):
    utils.rand_sleep()

    org = organization.get_by_id(org_id)
    if not org:
        raise flask.abort(401)

    user = org.get_user(id=user_id)
    if not user:
        raise flask.abort(401)

    sync_key = flask.request.json['sync_key']
    key_hash = flask.request.json['key_hash']

    if sync_key != user.sync_key:
        raise flask.abort(401)

    key_conf = user.sync_conf(server_id, key_hash)
    if key_conf:
        return key_conf['conf']
    return ''
Beispiel #21
0
def user_uri_key_page_get(short_id):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'short_id': short_id,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    org = organization.get_by_id(doc['org_id'])
    user = org.get_user(id=doc['user_id'])

    keys = {}
    for server in org.iter_servers():
        key = user.build_key_conf(server.id)
        keys[key['name']] = key['conf']

    return utils.jsonify(keys)
Beispiel #22
0
def user_linked_key_conf_get(key_id, server_id):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'key_id': key_id,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    org = organization.get_by_id(doc['org_id'])
    user = org.get_user(id=doc['user_id'])
    key_conf = user.build_key_conf(server_id)

    response = flask.Response(response=key_conf['conf'],
                              mimetype='application/octet-stream')
    response.headers.add('Content-Disposition',
                         'attachment; filename="%s"' % key_conf['name'])

    return response
Beispiel #23
0
def _find_doc(query, one_time=None, one_time_new=False):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one(query)

    if one_time and doc and doc.get('one_time'):
        if utils.now() - doc['timestamp'] > datetime.timedelta(
                seconds=settings.app.key_link_timeout_short):
            return None

        short_id = utils.rand_str(settings.app.long_url_length)
        collection = mongo.get_collection('users_key_link')

        if one_time_new:
            set_doc = {
                'short_id': short_id,
            }
        else:
            set_doc = {
                'one_time': 'used',
            }

        response = collection.update(
            {
                '_id': doc['_id'],
                'short_id': doc['short_id'],
                'one_time': True,
            }, {'$set': set_doc})
        if not response['updatedExisting']:
            return None

        if one_time_new:
            doc['short_id'] = short_id

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)

    return doc
Beispiel #24
0
def _find_doc(query, one_time=None):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one(query)

    if one_time and doc and doc.get('one_time'):
        collection = mongo.get_collection('users_key_link')
        response = collection.update({
            '_id': doc['_id'],
            'short_id': doc['short_id'],
            'one_time': True,
        }, {'$set': {
            'one_time': 'used',
        }})
        if not response['updatedExisting']:
            raise KeyError('Key link does not exists')

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)

    return doc
Beispiel #25
0
def user_linked_key_conf_get(key_id, server_id):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one({
        'key_id': key_id,
    })

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)
        return flask.abort(404)

    org = organization.get_by_id(doc['org_id'])
    user = org.get_user(id=doc['user_id'])
    key_conf = user.build_key_conf(server_id)

    response = flask.Response(response=key_conf['conf'],
        mimetype='application/octet-stream')
    response.headers.add('Content-Disposition',
        'attachment; filename="%s"' % key_conf['name'])

    return response
Beispiel #26
0
def key_sync_get(org_id, user_id, server_id, key_hash):
    if not settings.user.conf_sync:
        return utils.jsonify({})

    if not settings.local.sub_active:
        return utils.jsonify({}, status_code=480)

    utils.rand_sleep()

    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(401)
    auth_nonce = auth_nonce[:32]

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

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(401)

    user = org.get_user(id=user_id)
    if not user:
        return flask.abort(401)
    elif not user.sync_secret:
        return flask.abort(401)

    if auth_token != user.sync_token:
        return flask.abort(401)

    if user.disabled:
        return flask.abort(403)

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

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

    auth_test_signature = base64.b64encode(hmac.new(
        user.sync_secret.encode(), auth_string,
        hashlib.sha512).digest())
    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(401)

    key_conf = user.sync_conf(server_id, key_hash)
    if key_conf:
        user.audit_event('user_profile',
            'User profile synced from pritunl client',
            remote_addr=utils.get_remote_addr(),
        )

        sync_signature = base64.b64encode(hmac.new(
            user.sync_secret.encode(), key_conf['conf'],
            hashlib.sha512).digest())

        return utils.jsonify({
            'signature': sync_signature,
            'conf': key_conf['conf'],
        })

    return utils.jsonify({})
Beispiel #27
0
def key_sync_get(org_id, user_id, server_id, key_hash):
    if not settings.user.conf_sync:
        return utils.jsonify({})

    if not settings.local.sub_active:
        return utils.jsonify({}, status_code=480)

    utils.rand_sleep()

    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(401)
    auth_nonce = auth_nonce[:32]

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

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(401)

    user = org.get_user(id=user_id)
    if not user:
        return flask.abort(401)
    elif not user.sync_secret:
        return flask.abort(401)

    if auth_token != user.sync_token:
        return flask.abort(401)

    if user.disabled:
        return flask.abort(403)

    auth_string = "&".join(
        [user.sync_token, auth_timestamp, auth_nonce, flask.request.method, flask.request.path]
        + ([flask.request.data] if flask.request.data else [])
    )

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

    auth_test_signature = base64.b64encode(hmac.new(user.sync_secret.encode(), auth_string, hashlib.sha512).digest())
    if 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(401)

    key_conf = user.sync_conf(server_id, key_hash)
    if key_conf:
        user.audit_event("user_profile", "User profile synced from pritunl client", remote_addr=utils.get_remote_addr())

        sync_signature = base64.b64encode(
            hmac.new(user.sync_secret.encode(), key_conf["conf"], hashlib.sha512).digest()
        )

        return utils.jsonify({"signature": sync_signature, "conf": key_conf["conf"]})

    return utils.jsonify({})
Beispiel #28
0
def key_sync_get(org_id, user_id, server_id, key_hash):
    remote_addr = utils.get_remote_addr()

    if not settings.user.conf_sync:
        return utils.jsonify({})

    if not settings.local.sub_active:
        return utils.jsonify({}, status_code=480)

    utils.rand_sleep()

    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:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            remote_address=remote_addr,
            event_long='Missing auth header',
        )
        return flask.abort(406)
    auth_nonce = auth_nonce[:32]

    try:
        if abs(int(auth_timestamp) - int(utils.time_now())) > \
                settings.app.auth_time_window:
            journal.entry(
                journal.USER_SYNC_FAILURE,
                remote_address=remote_addr,
                event_long='Expired auth timestamp',
            )
            return flask.abort(408)
    except ValueError:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            remote_address=remote_addr,
            event_long='Invalid auth timestamp',
        )
        return flask.abort(405)

    org = organization.get_by_id(org_id)
    if not org:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            remote_address=remote_addr,
            event_long='Organization not found',
        )
        return flask.abort(404)

    usr = org.get_user(id=user_id)
    if not usr:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            remote_address=remote_addr,
            event_long='User not found',
        )
        return flask.abort(404)
    elif not usr.sync_secret:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='User missing sync secret',
        )
        return flask.abort(410)

    if auth_token != usr.sync_token:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='Sync token mismatch',
        )
        return flask.abort(410)

    if usr.disabled:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='User disabled',
        )
        return flask.abort(403)

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

    if len(auth_string) > AUTH_SIG_STRING_MAX_LEN:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='Auth string len limit exceeded',
        )
        return flask.abort(413)

    auth_test_signature = base64.b64encode(
        hmac.new(usr.sync_secret.encode(), auth_string,
                 hashlib.sha512).digest())
    if not utils.const_compare(auth_signature, auth_test_signature):
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='Sync signature mismatch',
        )
        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:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='Duplicate key',
        )
        return flask.abort(409)

    key_conf = usr.sync_conf(server_id, key_hash)
    if key_conf:
        usr.audit_event(
            'user_profile',
            'User profile synced from pritunl client',
            remote_addr=remote_addr,
        )

        journal.entry(
            journal.USER_SYNC_SUCCESS,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='User profile synced from pritunl client',
        )

        sync_signature = base64.b64encode(
            hmac.new(usr.sync_secret.encode(), key_conf['conf'],
                     hashlib.sha512).digest())

        return utils.jsonify({
            'signature': sync_signature,
            'conf': key_conf['conf'],
        })

    return utils.jsonify({})
Beispiel #29
0
def key_sync_get(org_id, user_id, server_id, key_hash):
    if not settings.user.conf_sync:
        return utils.jsonify({})

    if not settings.local.sub_active:
        return utils.jsonify({}, status_code=480)

    utils.rand_sleep()

    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(401)
    auth_nonce = auth_nonce[:32]

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

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(401)

    user = org.get_user(id=user_id)
    if not user:
        return flask.abort(401)
    elif not user.sync_secret:
        return flask.abort(401)

    if auth_token != user.sync_token:
        return flask.abort(401)

    if user.disabled:
        return flask.abort(403)

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

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

    auth_test_signature = base64.b64encode(
        hmac.new(user.sync_secret.encode(), auth_string,
                 hashlib.sha512).digest())
    if 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(401)

    key_conf = user.sync_conf(server_id, key_hash)
    if key_conf:
        user.audit_event(
            'user_profile',
            'User profile synced from pritunl client',
            remote_addr=utils.get_remote_addr(),
        )

        sync_signature = base64.b64encode(
            hmac.new(user.sync_secret.encode(), key_conf['conf'],
                     hashlib.sha512).digest())

        return utils.jsonify({
            'signature': sync_signature,
            'conf': key_conf['conf'],
        })

    return utils.jsonify({})
Beispiel #30
0
def key_sync_get(org_id, user_id, server_id, key_hash):
    remote_addr = utils.get_remote_addr()

    if not settings.user.conf_sync:
        return utils.jsonify({})

    if not settings.local.sub_active:
        return utils.jsonify({}, status_code=480)

    utils.rand_sleep()

    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:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            remote_address=remote_addr,
            event_long='Missing auth header',
        )
        return flask.abort(406)
    auth_nonce = auth_nonce[:32]

    try:
        if abs(int(auth_timestamp) - int(utils.time_now())) > \
                settings.app.auth_time_window:
            journal.entry(
                journal.USER_SYNC_FAILURE,
                remote_address=remote_addr,
                event_long='Expired auth timestamp',
            )
            return flask.abort(408)
    except ValueError:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            remote_address=remote_addr,
            event_long='Invalid auth timestamp',
        )
        return flask.abort(405)

    org = organization.get_by_id(org_id)
    if not org:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            remote_address=remote_addr,
            event_long='Organization not found',
        )
        return flask.abort(404)

    usr = org.get_user(id=user_id)
    if not usr:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            remote_address=remote_addr,
            event_long='User not found',
        )
        return flask.abort(404)
    elif not usr.sync_secret:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='User missing sync secret',
        )
        return flask.abort(410)

    if auth_token != usr.sync_token:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='Sync token mismatch',
        )
        return flask.abort(410)

    if usr.disabled:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='User disabled',
        )
        return flask.abort(403)

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

    if len(auth_string) > AUTH_SIG_STRING_MAX_LEN:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='Auth string len limit exceeded',
        )
        return flask.abort(413)

    auth_test_signature = base64.b64encode(hmac.new(
        usr.sync_secret.encode(), auth_string,
        hashlib.sha512).digest())
    if not utils.const_compare(auth_signature, auth_test_signature):
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='Sync signature mismatch',
        )
        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:
        journal.entry(
            journal.USER_SYNC_FAILURE,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='Duplicate key',
        )
        return flask.abort(409)

    key_conf = usr.sync_conf(server_id, key_hash)
    if key_conf:
        usr.audit_event('user_profile',
            'User profile synced from pritunl client',
            remote_addr=remote_addr,
        )

        journal.entry(
            journal.USER_SYNC_SUCCESS,
            usr.journal_data,
            remote_address=remote_addr,
            event_long='User profile synced from pritunl client',
        )

        sync_signature = base64.b64encode(hmac.new(
            usr.sync_secret.encode(), key_conf['conf'],
            hashlib.sha512).digest())

        return utils.jsonify({
            'signature': sync_signature,
            'conf': key_conf['conf'],
        })

    return utils.jsonify({})