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({})
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
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('')
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
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('')
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({})
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({})
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
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
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 ''
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'])
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 ''
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({})
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
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
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)
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 ''
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)
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
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
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
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({})
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({})
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({})
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({})
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({})