def server_client_connect_post(server_id): org_id = flask.request.json['org_id'] user_id = flask.request.json['user_id'] server = Server(server_id) if not server: return utils.jsonify({ 'error': SERVER_INVALID, 'error_msg': SERVER_INVALID_MSG, }, 401) org = server.get_org(org_id) if not org: return utils.jsonify({ 'error': ORG_INVALID, 'error_msg': ORG_INVALID_MSG, }, 401) user = org.get_user(user_id) if not user: return utils.jsonify({ 'error': USER_INVALID, 'error_msg': USER_INVALID_MSG, }, 401) return utils.jsonify({ 'client_conf': None, })
def server_tls_verify_post(server_id): org_id = flask.request.json['org_id'] user_id = flask.request.json['user_id'] server = Server(server_id) if not server: return utils.jsonify({ 'error': SERVER_INVALID, 'error_msg': SERVER_INVALID_MSG, }, 401) org = server.get_org(org_id) if not org: LogEntry(message='User failed authentication, ' + 'invalid organization "%s".' % server.name) return utils.jsonify({ 'error': ORG_INVALID, 'error_msg': ORG_INVALID_MSG, }, 401) user = org.get_user(user_id) if not user: LogEntry(message='User failed authentication, ' + 'invalid user "%s".' % server.name) return utils.jsonify({ 'error': USER_INVALID, 'error_msg': USER_INVALID_MSG, }, 401) return utils.jsonify({ 'authenticated': True, })
def server_link_put(server_id, link_server_id): if settings.app.demo_mode: return utils.demo_blocked() use_local_address = flask.request.json.get('use_local_address', False) try: server.link_servers(server_id, link_server_id, use_local_address) except ServerLinkOnlineError: return utils.jsonify({ 'error': SERVER_NOT_OFFLINE, 'error_msg': SERVER_NOT_OFFLINE_LINK_SERVER_MSG, }, 400) except ServerLinkCommonHostError: return utils.jsonify({ 'error': SERVER_LINK_COMMON_HOST, 'error_msg': SERVER_LINK_COMMON_HOST_MSG, }, 400) except ServerLinkCommonRouteError: return utils.jsonify({ 'error': SERVER_LINK_COMMON_ROUTE, 'error_msg': SERVER_LINK_COMMON_ROUTE_MSG, }, 400) except ServerLinkReplicaError: return utils.jsonify({ 'error': SERVER_LINKS_AND_REPLICA, 'error_msg': SERVER_LINKS_AND_REPLICA_MSG, }, 400) event.Event(type=SERVER_LINKS_UPDATED, resource_id=server_id) event.Event(type=SERVER_LINKS_UPDATED, resource_id=link_server_id) event.Event(type=SERVER_ROUTES_UPDATED, resource_id=server_id) event.Event(type=SERVER_ROUTES_UPDATED, resource_id=link_server_id) return utils.jsonify({})
def link_get(): if not settings.local.sub_plan or \ 'enterprise' not in settings.local.sub_plan: return flask.abort(404) if settings.app.demo_mode: resp = utils.demo_get_cache() if resp: return utils.jsonify(resp) page = flask.request.args.get('page', None) page = int(page) if page else page links = [] for lnk in link.iter_links(page): links.append(lnk.dict()) data = { 'page': page, 'page_total': link.get_page_total(), 'links': links, } if settings.app.demo_mode: utils.demo_set_cache(data) return utils.jsonify(data)
def event_get(last_event=None): if app_server.interrupt: return flask.abort(503) if not last_event: events = [ { 'id': uuid.uuid4().hex, 'type': 'time', 'resource_id': None, 'time': int(time.time() * 1000), }, ] return utils.jsonify(events) run_time = 0 while run_time <= 30 and not app_server.interrupt: events = [] for event in Event.get_events(last_event): events.append({ 'id': event.id, 'type': event.type, 'resource_id': event.resource_id, 'time': event.time, }) if len(events): return utils.jsonify(events) run_time += 0.1 time.sleep(0.1) return utils.jsonify([])
def admin_post(): if settings.app.demo_mode: return utils.demo_blocked() if not flask.g.administrator.super_user: return utils.jsonify({"error": REQUIRES_SUPER_USER, "error_msg": REQUIRES_SUPER_USER_MSG}, 400) username = utils.filter_str(flask.request.json["username"]) password = flask.request.json["password"] otp_auth = flask.request.json.get("otp_auth", False) auth_api = flask.request.json.get("auth_api", False) disabled = flask.request.json.get("disabled", False) super_user = flask.request.json.get("super_user", False) try: admin = auth.new_admin( username=username, password=password, default=True, otp_auth=otp_auth, auth_api=auth_api, disabled=disabled, super_user=super_user, ) except pymongo.errors.DuplicateKeyError: return utils.jsonify({"error": ADMIN_USERNAME_EXISTS, "error_msg": ADMIN_USERNAME_EXISTS_MSG}, 400) admin.audit_event("admin_created", "Administrator created", remote_addr=utils.get_remote_addr()) event.Event(type=ADMINS_UPDATED) return utils.jsonify(admin.dict())
def subscription_post(): license = flask.request.json['license'] license = license.lower().replace('begin license', '').replace( 'end license', '') license = re.sub(r'[\W_]+', '', license) try: response = utils.request.get( 'https://app.pritunl.com/subscription', json_data={ 'license': license, 'version': settings.local.version_int, }, ) except httplib.HTTPException: return utils.jsonify({ 'error': SUBSCRIPTION_SERVER_ERROR, 'error_msg': SUBSCRIPTION_SERVER_ERROR_MSG, }, 500) data = response.json() if response.status_code != 200: return utils.jsonify(data, response.status_code) subscription.update_license(license) return utils.jsonify(subscription.dict())
def server_host_put(server_id, host_id): if settings.app.demo_mode: return utils.demo_blocked() svr = server.get_by_id(server_id, fields=('_id', 'hosts', 'links')) hst = host.get_by_id(host_id, fields=('_id', 'name', 'public_address', 'auto_public_address')) try: svr.add_host(hst.id) except ServerLinkCommonHostError: return utils.jsonify({ 'error': SERVER_LINK_COMMON_HOST, 'error_msg': SERVER_LINK_COMMON_HOST_MSG, }, 400) svr.commit('hosts') event.Event(type=SERVER_HOSTS_UPDATED, resource_id=svr.id) return utils.jsonify({ 'id': hst.id, 'server': svr.id, 'status': OFFLINE, 'name': hst.name, 'address': hst.public_addr, })
def user_post(org_id): if settings.app.demo_mode: return utils.demo_blocked() remote_addr = utils.get_remote_addr() if isinstance(flask.request.json, list): users_data = flask.request.json else: users_data = [flask.request.json] if len(users_data) > 10: if _users_background: return utils.jsonify({ 'error': USERS_BACKGROUND_BUSY, 'error_msg': USERS_BACKGROUND_BUSY_MSG, }, 429) thread = threading.Thread( target=_create_users, args=(org_id, users_data, remote_addr, True), ) thread.daemon = True thread.start() return utils.jsonify({ 'status': USERS_BACKGROUND, 'status_msg': USERS_BACKGROUND_MSG, }, 202) return _create_users(org_id, users_data, remote_addr, False)
def _auth_radius(username, password): valid, org_id = sso.verify_radius(username, password) if not valid: return utils.jsonify({"error": AUTH_INVALID, "error_msg": AUTH_INVALID_MSG}, 401) if not org_id: org_id = settings.app.sso_org org = organization.get_by_id(org_id) if not org: return flask.abort(405) usr = org.find_user(name=username) if not usr: usr = org.new_user(name=username, type=CERT_CLIENT, auth_type=RADIUS_AUTH) usr.audit_event("user_created", "User created with single sign-on", remote_addr=utils.get_remote_addr()) event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) else: if usr.disabled: return utils.jsonify({"error": AUTH_DISABLED, "error_msg": AUTH_DISABLED_MSG}, 403) if usr.auth_type != RADIUS_AUTH: usr.auth_type = RADIUS_AUTH usr.set_pin(None) usr.commit(("auth_type", "pin")) key_link = org.create_user_key_link(usr.id, one_time=True) usr.audit_event("user_profile", "User profile viewed from single sign-on", remote_addr=utils.get_remote_addr()) return utils.jsonify({"redirect": flask.request.url_root[:-1] + key_link["view_url"]}, 202)
def admin_delete(admin_id): if settings.app.demo_mode: return utils.demo_blocked() if not flask.g.administrator.super_user: return utils.jsonify({ 'error': REQUIRES_SUPER_USER, 'error_msg': REQUIRES_SUPER_USER_MSG, }, 400) admin = auth.get_by_id(admin_id) remote_addr = utils.get_remote_addr() if admin.super_user and auth.super_user_count() < 2: return utils.jsonify({ 'error': NO_ADMINS, 'error_msg': NO_ADMINS_MSG, }, 400) journal.entry( journal.ADMIN_DELETE, admin.journal_data, event_long='Administrator deleted', remote_addr=remote_addr, ) admin.remove() event.Event(type=ADMINS_UPDATED) return utils.jsonify({})
def server_org_delete(server_id, org_id): if settings.app.demo_mode: return utils.demo_blocked() svr = server.get_by_id(server_id, fields=('_id', 'status', 'network', 'network_start', 'network_end', 'primary_organization', 'primary_user', 'organizations', 'routes', 'ipv6')) org = organization.get_by_id(org_id, fields=('_id')) if svr.status == ONLINE: return utils.jsonify({ 'error': SERVER_NOT_OFFLINE, 'error_msg': SERVER_NOT_OFFLINE_DETACH_ORG_MSG, }, 400) svr.remove_org(org) svr.commit(svr.changed) event.Event(type=SERVERS_UPDATED) event.Event(type=SERVER_ROUTES_UPDATED, resource_id=svr.id) event.Event(type=SERVER_ORGS_UPDATED, resource_id=svr.id) event.Event(type=USERS_UPDATED, resource_id=org.id) return utils.jsonify({})
def auth_session_post(): username = flask.request.json["username"] password = flask.request.json["password"] otp_code = flask.request.json.get("otp_code") remote_addr = utils.get_remote_addr() admin = auth.get_by_username(username, remote_addr) if not admin: if settings.app.sso == RADIUS_AUTH: return _auth_radius(username, password) time.sleep(random.randint(0, 100) / 1000.0) return utils.jsonify({"error": AUTH_INVALID, "error_msg": AUTH_INVALID_MSG}, 401) if not otp_code and admin.otp_auth: return utils.jsonify({"error": AUTH_OTP_REQUIRED, "error_msg": AUTH_OTP_REQUIRED_MSG}, 402) if not admin.auth_check(password, otp_code, remote_addr): time.sleep(random.randint(0, 100) / 1000.0) return utils.jsonify({"error": AUTH_INVALID, "error_msg": AUTH_INVALID_MSG}, 401) flask.session["session_id"] = admin.new_session() flask.session["admin_id"] = str(admin.id) flask.session["timestamp"] = int(utils.time_now()) if not settings.conf.ssl: flask.session["source"] = remote_addr return utils.jsonify({"authenticated": True, "default": admin.default or False})
def host_get(hst=None): if settings.app.demo_mode: resp = utils.demo_get_cache() if resp: return utils.jsonify(resp) if hst: resp = host.get_by_id(hst).dict() if settings.app.demo_mode: utils.demo_set_cache(resp) return utils.jsonify(resp) hosts = [] page = flask.request.args.get('page', None) page = int(page) if page else page for hst in host.iter_hosts_dict(page=page): hosts.append(hst) if page is not None: resp = { 'page': page, 'page_total': host.get_host_page_total(), 'hosts': hosts, } else: resp = hosts if settings.app.demo_mode: utils.demo_set_cache(resp) return utils.jsonify(resp)
def server_route_delete(server_id, route_network): if settings.app.demo_mode: return utils.demo_blocked() svr = server.get_by_id(server_id) route_network = route_network.decode('hex') try: route = svr.remove_route(route_network) except ServerOnlineError: return utils.jsonify({ 'error': SERVER_ROUTE_ONLINE, 'error_msg': SERVER_ROUTE_ONLINE_MSG, }, 400) err, err_msg = svr.validate_conf() if err: return utils.jsonify({ 'error': err, 'error_msg': err_msg, }, 400) svr.commit('routes') event.Event(type=SERVER_ROUTES_UPDATED, resource_id=svr.id) for svr_link in svr.links: event.Event(type=SERVER_ROUTES_UPDATED, resource_id=svr_link['server_id']) return utils.jsonify(route)
def link_location_route_post(link_id, location_id): if not settings.local.sub_plan or \ 'enterprise' not in settings.local.sub_plan: return flask.abort(404) if settings.app.demo_mode: return utils.demo_blocked() lnk = link.get_by_id(link_id) if not lnk: return flask.abort(404) loc = lnk.get_location(location_id) if not loc: return flask.abort(404) try: network = loc.add_route(flask.request.json.get('network')) except NetworkInvalid: return utils.jsonify({ 'error': LINK_NETWORK_INVALID, 'error_msg': LINK_NETWORK_INVALID_MSG, }, 400) loc.commit('routes') event.Event(type=LINKS_UPDATED) return utils.jsonify({ 'id': network, })
def setup_mongodb_put(): mongodb_uri = flask.request.json['mongodb_uri'] 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.ConnectionFailure: return utils.jsonify({ 'error': MONGODB_CONNECT_ERROR, 'error_msg': MONGODB_CONNECT_ERROR_MSG, }, 400) settings.conf.mongodb_uri = mongodb_uri settings.conf.commit() if server_ready: stop_server() else: upgrade_database() return ''
def sso_duo_post(): sso_mode = settings.app.sso token = utils.filter_str(flask.request.json.get("token")) or None passcode = utils.filter_str(flask.request.json.get("passcode")) or None if not token or not passcode: return utils.jsonify({"error": TOKEN_INVALID, "error_msg": TOKEN_INVALID_MSG}, 401) tokens_collection = mongo.get_collection("sso_tokens") doc = tokens_collection.find_one({"_id": token}) if not doc or doc["_id"] != token: return utils.jsonify({"error": TOKEN_INVALID, "error_msg": TOKEN_INVALID_MSG}, 401) username = doc["username"] email = doc["email"] org_id = doc["org_id"] groups = doc["groups"] duo_auth = sso.Duo( username=username, factor=settings.app.sso_duo_mode, remote_ip=utils.get_remote_addr(), auth_type="Key", passcode=passcode, ) valid = duo_auth.authenticate() if not valid: return utils.jsonify({"error": PASSCODE_INVALID, "error_msg": PASSCODE_INVALID_MSG}, 401) org = organization.get_by_id(org_id) if not org: return flask.abort(405) usr = org.find_user(name=username) if not usr: usr = org.new_user( name=username, email=email, type=CERT_CLIENT, auth_type=sso_mode, groups=list(groups) if groups else None ) usr.audit_event("user_created", "User created with single sign-on", remote_addr=utils.get_remote_addr()) event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) else: if usr.disabled: return flask.abort(403) if groups and groups - set(usr.groups or []): usr.groups = list(set(usr.groups or []) | groups) usr.commit("groups") if usr.auth_type != sso_mode: usr.auth_type = sso_mode usr.commit("auth_type") key_link = org.create_user_key_link(usr.id, one_time=True) usr.audit_event("user_profile", "User profile viewed from single sign-on", remote_addr=utils.get_remote_addr()) return utils.jsonify({"redirect": utils.get_url_root() + key_link["view_url"]}, 200)
def mongodb_put(): mongodb_uri = flask.request.json['mongodb_uri'] 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) 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() dbconf_ready.set() settings.local.server_ready.wait() threading.Thread(target=stop_server).start() return ''
def user_post(org_id): org = organization.get_org(id=org_id) users = [] if isinstance(flask.request.json, list): users_data = flask.request.json else: users_data = [flask.request.json] for user_data in users_data: name = utils.filter_str(user_data['name']) email = utils.filter_str(user_data.get('email')) disabled = user_data.get('disabled') user = org.new_user(type=CERT_CLIENT, name=name, email=email, disabled=disabled) users.append(user.dict()) event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) if isinstance(flask.request.json, list): logger.LogEntry(message='Created %s new users.' % len( flask.request.json)) return utils.jsonify(users) else: logger.LogEntry(message='Created new user "%s".' % users[0]['name']) return utils.jsonify(users[0])
def admin_get(admin_id=None): if settings.app.demo_mode: resp = utils.demo_get_cache() if resp: return utils.jsonify(resp) if not flask.g.administrator.super_user: return utils.jsonify({ 'error': REQUIRES_SUPER_USER, 'error_msg': REQUIRES_SUPER_USER_MSG, }, 400) if admin_id: return utils.jsonify(auth.get_by_id(admin_id).dict()) admins = [] for admin in auth.iter_admins(): admin = admin.dict() admin['audit'] = settings.app.auditing == ALL admins.append(admin) if settings.app.demo_mode: utils.demo_set_cache(admins) return utils.jsonify(admins)
def server_route_delete(server_id, route_network): if settings.app.demo_mode: return utils.demo_blocked() svr = server.get_by_id(server_id, fields=('_id', 'network', 'links', 'network_start', 'network_end', 'routes', 'organizations', 'status', 'ipv6')) route_network = route_network.decode('hex') try: route = svr.remove_route(route_network) except ServerOnlineError: return utils.jsonify({ 'error': SERVER_ROUTE_ONLINE, 'error_msg': SERVER_ROUTE_ONLINE_MSG, }, 400) svr.commit('routes') event.Event(type=SERVER_ROUTES_UPDATED, resource_id=svr.id) for svr_link in svr.links: event.Event(type=SERVER_ROUTES_UPDATED, resource_id=svr_link['server_id']) return utils.jsonify(route)
def server_client_disconnect_post(server_id): org_id = bson.ObjectId(flask.request.json['org_id']) user_id = bson.ObjectId(flask.request.json['user_id']) svr = server.get_by_id(server_id, fields=['_id', 'organizations']) if not svr: return utils.jsonify({ 'error': SERVER_INVALID, 'error_msg': SERVER_INVALID_MSG, }, 401) org = svr.get_org(org_id, fields=['_id']) if not org: return utils.jsonify({ 'error': ORG_INVALID, 'error_msg': ORG_INVALID_MSG, }, 401) user = org.get_user(user_id, fields=['_id']) if not user: return utils.jsonify({ 'error': USER_INVALID, 'error_msg': USER_INVALID_MSG, }, 401) return utils.jsonify({})
def subscription_put(): card = flask.request.json.get('card') email = flask.request.json.get('email') cancel = flask.request.json.get('cancel') try: if cancel: response = utils.request.delete(SUBSCRIPTION_SERVER, json_data={ 'license': persist_db.get('license'), }, ) else: response = utils.request.put(SUBSCRIPTION_SERVER, json_data={ 'license': persist_db.get('license'), 'card': card, 'email': email, }, ) except httplib.HTTPException: return utils.jsonify({ 'error': SUBSCRIPTION_SERVER_ERROR, 'error_msg': SUBSCRIPTION_SERVER_ERROR_MSG, }, 500) if response.status_code != 200: return utils.jsonify(response.json(), response.status_code) app_server.subscription_update() return utils.jsonify(app_server.subscription_dict())
def server_host_get(server_id): if settings.app.demo_mode: resp = utils.demo_get_cache() if resp: return utils.jsonify(resp) hosts = [] svr = server.get_by_id(server_id, fields=('_id', 'status', 'replica_count', 'hosts', 'instances')) active_hosts = set([x['host_id'] for x in svr.instances]) hosts_offline = svr.replica_count - len(active_hosts) > 0 for hst in svr.iter_hosts(fields=('_id', 'name', 'public_address', 'auto_public_address', 'public_address6', 'auto_public_address6')): if svr.status == ONLINE and hst.id in active_hosts: status = ONLINE elif svr.status == ONLINE and hosts_offline: status = OFFLINE else: status = None hosts.append({ 'id': hst.id, 'server': svr.id, 'status': status, 'name': hst.name, 'address': hst.public_addr, 'address6': hst.public_addr6, }) if settings.app.demo_mode: utils.demo_set_cache(hosts) return utils.jsonify(hosts)
def org_get(org_id=None): if org_id: return utils.jsonify(organization.get_by_id(org_id).dict()) orgs = [] for org in organization.iter_orgs_dict(): orgs.append(org) return utils.jsonify(orgs)
def org_get(org_id=None): if org_id: return utils.jsonify(Organization.get_org(id=org_id).dict()) else: orgs = [] for org in Organization.iter_orgs(): orgs.append(org.dict()) return utils.jsonify(orgs)
def user_audit_get(org_id, user_id): if org_id == 'admin' and user_id == 'admin': return utils.jsonify(auth.get_audit_events()) org = organization.get_by_id(org_id) user = org.get_user(user_id) return utils.jsonify(user.get_audit_events())
def server_org_put(server_id, org_id): server = Server(server_id) if server.status: return utils.jsonify({ 'error': SERVER_NOT_OFFLINE, 'error_msg': SERVER_NOT_OFFLINE_MSG, }, 400) server.add_org(org_id) return utils.jsonify({})
def user_put(org_id, user_id): org = Organization.get_org(id=org_id) user = org.get_user(user_id) name = flask.request.json.get('name') if name: name = utils.filter_str(name) if 'email' in flask.request.json: email = flask.request.json['email'] if email: user.email = utils.filter_str(email) else: user.email = None disabled = flask.request.json.get('disabled') if disabled is not None: user.disabled = disabled if name: user.rename(name) else: user.commit() Event(type=USERS_UPDATED, resource_id=user.org.id) if disabled: if user.type == CERT_CLIENT: LogEntry(message='Disabled user "%s".' % user.name) for server in org.iter_servers(): server_clients = server.clients if user_id in server_clients: server.restart() elif disabled == False and user.type == CERT_CLIENT: LogEntry(message='Enabled user "%s".' % user.name) send_key_email = flask.request.json.get('send_key_email') if send_key_email and user.email: try: user.send_key_email(send_key_email) except EmailNotConfiguredError: return utils.jsonify({ 'error': EMAIL_NOT_CONFIGURED, 'error_msg': EMAIL_NOT_CONFIGURED_MSG, }, 400) except EmailFromInvalid: return utils.jsonify({ 'error': EMAIL_FROM_INVALID, 'error_msg': EMAIL_FROM_INVALID_MSG, }, 400) except EmailApiKeyInvalid: return utils.jsonify({ 'error': EMAIL_API_KEY_INVALID, 'error_msg': EMAIL_API_KEY_INVALID_MSG, }, 400) return utils.jsonify(user.dict())
def auth_user_post(): 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 utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) auth_nonce = auth_nonce[:32] try: if abs(int(auth_timestamp) - int(utils.time_now())) > \ settings.app.auth_time_window: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) except ValueError: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) org = organization.get_by_token(auth_token) if not org: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 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 utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) if not org.auth_secret or len(org.auth_secret) < 8: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) auth_test_signature = base64.b64encode(hmac.new( org.auth_secret.encode(), auth_string, hashlib.sha256).digest()) if auth_signature != auth_test_signature: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) try: org.nonces_collection.insert({ 'token': auth_token, 'nonce': auth_nonce, 'timestamp': utils.now(), }) except pymongo.errors.DuplicateKeyError: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) username = flask.request.json['username'] network_links = flask.request.json.get('network_links') usr = org.find_user(name=username) if usr: usr.remove() usr = org.new_user(name=username, type=CERT_CLIENT) usr.audit_event('user_created', 'User created with authentication token', remote_addr=utils.get_remote_addr()) if network_links: for network_link in network_links: try: usr.add_network_link(network_link, force=True) except (ipaddress.AddressValueError, ValueError): return _network_link_invalid() event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) keys = {} for svr in org.iter_servers(): key = usr.build_key_conf(svr.id) keys[key['name']] = key['conf'] return utils.jsonify(keys)
def _auth_plugin(username, password, remote_addr): if not settings.local.sub_plan or \ 'enterprise' not in settings.local.sub_plan: journal.entry( journal.ADMIN_AUTH_FAILURE, user_name=username, remote_address=remote_addr, reason=journal.ADMIN_AUTH_REASON_INVALID_USERNAME, reason_long='Invalid username', ) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) has_plugin, valid, org_id, groups = sso.plugin_login_authenticate( user_name=username, password=password, remote_ip=remote_addr, ) if not has_plugin: journal.entry( journal.ADMIN_AUTH_FAILURE, user_name=username, remote_address=remote_addr, reason=journal.ADMIN_AUTH_REASON_INVALID_USERNAME, reason_long='Invalid username', ) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) if not valid: journal.entry( journal.SSO_AUTH_REASON_PLUGIN_FAILED, user_name=username, remote_address=remote_addr, reason=journal.SSO_AUTH_REASON_PLUGIN_FAILED, reason_long='Plugin authentication failed', ) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) if not org_id: logger.error( 'Login plugin did not return valid organization name', 'auth', org_name=org_id, user_name=username, ) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) org = organization.get_by_id(org_id) if not org: return flask.abort(405) usr = org.find_user(name=username) if not usr: usr = org.new_user(name=username, type=CERT_CLIENT, auth_type=PLUGIN_AUTH, groups=list(groups) if groups else None) usr.audit_event( 'user_created', 'User created with plugin authentication', remote_addr=utils.get_remote_addr(), ) journal.entry( journal.USER_CREATE, usr.journal_data, event_long='User created with plugin authentication', remote_address=remote_addr, ) event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) else: if usr.disabled: return utils.jsonify( { 'error': AUTH_DISABLED, 'error_msg': AUTH_DISABLED_MSG, }, 403) if groups and groups - set(usr.groups or []): usr.groups = list(set(usr.groups or []) | groups) usr.commit('groups') if usr.auth_type != PLUGIN_AUTH: usr.auth_type = PLUGIN_AUTH usr.set_pin(None) usr.commit(('auth_type', 'pin')) key_link = org.create_user_key_link(usr.id, one_time=True) usr.audit_event( 'user_profile', 'User profile viewed from plugin authentication', remote_addr=utils.get_remote_addr(), ) journal.entry( journal.USER_PROFILE_SUCCESS, usr.journal_data, event_long='User profile viewed from plugin authentication', remote_address=remote_addr, ) return utils.jsonify( { 'redirect': utils.get_url_root() + key_link['view_url'], }, 202)
def _interface_invalid(): return utils.jsonify( { 'error': INTERFACE_INVALID, 'error_msg': INTERFACE_INVALID_MSG, }, 400)
def _dns_server_invalid(): return utils.jsonify( { 'error': DNS_SERVER_INVALID, 'error_msg': DNS_SERVER_INVALID_MSG, }, 400)
def server_bandwidth_get(server_id, period): svr = server.get_server(id=server_id) return utils.jsonify(svr.bandwidth.get_period(period))
def key_sync_get(org_id, user_id, server_id, key_hash): org_id = org_id user_id = user_id server_id = server_id key_hash = key_hash[:256] 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_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: 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.encode(), hashlib.sha512).digest()).decode() 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'].encode(), hashlib.sha512).digest()).decode() return utils.jsonify({ 'signature': sync_signature, 'conf': key_conf['conf'], }) return utils.jsonify({})
def user_key_pin_put(key_id): if settings.app.demo_mode: return utils.demo_blocked() key_id = key_id[:128] remote_addr = utils.get_remote_addr() doc = _find_doc({ 'key_id': key_id, }) if not doc: journal.entry( journal.USER_PROFILE_FAILURE, remote_address=remote_addr, event_long='Key ID not found', ) return flask.abort(404) if settings.user.pin_mode == PIN_DISABLED: return utils.jsonify({ 'error': PIN_IS_DISABLED, 'error_msg': PIN_IS_DISABLED_MSG, }, 400) org = organization.get_by_id(doc['org_id']) usr = org.get_user(doc['user_id']) if usr.disabled: return flask.abort(403) if RADIUS_AUTH in usr.auth_type: return utils.jsonify({ 'error': PIN_RADIUS, 'error_msg': PIN_RADIUS_MSG, }, 400) current_pin = utils.filter_str( flask.request.json.get('current_pin')) or None pin = utils.filter_str(flask.request.json.get('pin')) or None if pin: if settings.user.pin_digits_only and not pin.isdigit(): return utils.jsonify({ 'error': PIN_NOT_DIGITS, 'error_msg': PIN_NOT_DIGITS_MSG, }, 400) if len(pin) < settings.user.pin_min_length: return utils.jsonify({ 'error': PIN_TOO_SHORT, 'error_msg': PIN_TOO_SHORT_MSG, }, 400) if usr.pin: if not limiter.auth_check(usr.id): return utils.jsonify({ 'error': AUTH_TOO_MANY, 'error_msg': AUTH_TOO_MANY_MSG, }, 400) if not usr.check_pin(current_pin): return utils.jsonify({ 'error': PIN_INVALID, 'error_msg': PIN_INVALID_MSG, }, 400) if usr.set_pin(pin): journal.entry( journal.USER_PIN_UPDATE, usr.journal_data, remote_address=remote_addr, event_long='User pin changed with temporary profile link', ) usr.audit_event('user_updated', 'User pin changed with temporary profile link', remote_addr=remote_addr, ) usr.commit() event.Event(type=USERS_UPDATED, resource_id=org.id) return utils.jsonify({})
def settings_zones_get(): return utils.jsonify(utils.get_zones())
def sso_duo_post(): sso_mode = settings.app.sso token = utils.filter_str(flask.request.json.get('token')) or None passcode = utils.filter_str(flask.request.json.get('passcode')) or '' if sso_mode not in (DUO_AUTH, GOOGLE_DUO_AUTH, SLACK_DUO_AUTH, SAML_DUO_AUTH, SAML_OKTA_DUO_AUTH, SAML_ONELOGIN_DUO_AUTH, RADIUS_DUO_AUTH): return flask.abort(404) if not token: return utils.jsonify( { 'error': TOKEN_INVALID, 'error_msg': TOKEN_INVALID_MSG, }, 401) tokens_collection = mongo.get_collection('sso_tokens') doc = tokens_collection.find_one({ '_id': token, }) if not doc or doc['_id'] != token or doc['type'] != DUO_AUTH: return utils.jsonify( { 'error': TOKEN_INVALID, 'error_msg': TOKEN_INVALID_MSG, }, 401) username = doc['username'] email = doc['email'] org_id = doc['org_id'] groups = set(doc['groups'] or []) if settings.app.sso_duo_mode == 'passcode': duo_auth = sso.Duo( username=username, factor=settings.app.sso_duo_mode, remote_ip=utils.get_remote_addr(), auth_type='Key', passcode=passcode, ) valid = duo_auth.authenticate() if not valid: logger.error( 'Duo authentication not valid', 'sso', username=username, ) return utils.jsonify( { 'error': PASSCODE_INVALID, 'error_msg': PASSCODE_INVALID_MSG, }, 401) else: duo_auth = sso.Duo( username=username, factor=settings.app.sso_duo_mode, remote_ip=utils.get_remote_addr(), auth_type='Key', ) valid = duo_auth.authenticate() if not valid: logger.error( 'Duo authentication not valid', 'sso', username=username, ) return utils.jsonify( { 'error': DUO_FAILED, 'error_msg': DUO_FAILED_MSG, }, 401) valid, org_id_new, groups2 = sso.plugin_sso_authenticate( sso_type='duo', user_name=username, user_email=email, remote_ip=utils.get_remote_addr(), ) if valid: org_id = org_id_new or org_id else: logger.error( 'Duo plugin authentication not valid', 'sso', username=username, ) return flask.abort(401) groups = groups | set(groups2 or []) usr = user.find_user_auth(name=username, auth_type=sso_mode) if not usr: org = organization.get_by_id(org_id) if not org: return flask.abort(405) usr = org.find_user(name=username) else: org = usr.org if not usr: usr = org.new_user(name=username, email=email, type=CERT_CLIENT, auth_type=sso_mode, groups=list(groups) if groups else None) usr.audit_event('user_created', 'User created with single sign-on', remote_addr=utils.get_remote_addr()) event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) else: if usr.disabled: return flask.abort(403) if groups and groups - set(usr.groups or []): usr.groups = list(set(usr.groups or []) | groups) usr.commit('groups') if usr.auth_type != sso_mode: usr.auth_type = sso_mode usr.commit('auth_type') key_link = org.create_user_key_link(usr.id, one_time=True) usr.audit_event( 'user_profile', 'User profile viewed from single sign-on', remote_addr=utils.get_remote_addr(), ) return utils.jsonify( { 'redirect': utils.get_url_root() + key_link['view_url'], }, 200)
def settings_put(): admin = flask.g.administrator if 'username' in flask.request.json and flask.request.json['username']: admin.username = utils.filter_str( flask.request.json['username']).lower() if 'password' in flask.request.json and flask.request.json['password']: admin.password = flask.request.json['password'] if 'token' in flask.request.json and flask.request.json['token']: admin.generate_token() if 'secret' in flask.request.json and flask.request.json['secret']: admin.generate_secret() settings_commit = False if 'email_from' in flask.request.json: settings_commit = True email_from = flask.request.json['email_from'] settings.app.email_from = email_from or None if 'email_server' in flask.request.json: settings_commit = True email_server = flask.request.json['email_server'] settings.app.email_server = email_server or None if 'email_username' in flask.request.json: settings_commit = True email_username = flask.request.json['email_username'] settings.app.email_username = email_username or None if 'email_password' in flask.request.json: settings_commit = True email_password = flask.request.json['email_password'] settings.app.email_password = email_password or None if 'sso' in flask.request.json: settings_commit = True sso = flask.request.json['sso'] settings.app.sso = sso or None if 'sso_match' in flask.request.json: sso_match = flask.request.json['sso_match'] if isinstance(sso_match, list): settings_commit = True settings.app.sso_match = sso_match or None if 'sso_org' in flask.request.json: settings_commit = True sso_org = flask.request.json['sso_org'] if sso_org: settings.app.sso_org = utils.ObjectId(sso_org) else: settings.app.sso_org = None if 'theme' in flask.request.json: settings_commit = True theme = 'dark' if flask.request.json['theme'] == 'dark' else 'light' if theme != settings.app.theme: if theme == 'dark': event.Event(type=THEME_DARK) else: event.Event(type=THEME_LIGHT) settings.app.theme = theme if 'public_address' in flask.request.json: public_address = flask.request.json['public_address'] settings.local.host.public_address = public_address settings.local.host.commit('public_address') if 'server_cert' in flask.request.json: settings_commit = True server_cert = flask.request.json['server_cert'] if server_cert: settings.app.server_cert = server_cert.strip() else: settings.app.server_cert = None if 'server_key' in flask.request.json: settings_commit = True server_key = flask.request.json['server_key'] if server_key: settings.app.server_key = server_key.strip() else: settings.app.server_key = None if settings_commit: settings.commit() admin.commit(admin.changed) response = flask.g.administrator.dict() response.update({ 'theme': settings.app.theme, 'email_from': settings.app.email_from, 'email_server': settings.app.email_server, 'email_username': settings.app.email_username, 'email_password': bool(settings.app.email_password), 'sso': bool(settings.app.sso), 'sso_match': settings.app.sso_match, 'sso_org': settings.app.sso_org, 'public_address': settings.local.host.public_addr, }) return utils.jsonify(response)
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(406) auth_nonce = auth_nonce[:32] 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) org = organization.get_by_id(org_id) if not org: return flask.abort(404) usr = org.get_user(id=user_id) if not usr: return flask.abort(404) elif not usr.sync_secret: return flask.abort(410) if auth_token != usr.sync_token: return flask.abort(410) if usr.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: 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): 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) 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=utils.get_remote_addr(), ) 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_wg_post(org_id, user_id, server_id): org_id = org_id user_id = user_id server_id = server_id remote_addr = utils.get_remote_addr() 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_WG_FAILURE, remote_address=remote_addr, event_long='Missing auth header', ) 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: journal.entry( journal.USER_WG_FAILURE, remote_address=remote_addr, event_long='Expired auth timestamp', ) return flask.abort(408) except ValueError: journal.entry( journal.USER_WG_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_WG_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_WG_FAILURE, remote_address=remote_addr, event_long='User not found', ) return flask.abort(404) elif not usr.sync_secret: journal.entry( journal.USER_WG_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_WG_FAILURE, usr.journal_data, remote_address=remote_addr, event_long='Sync token mismatch', ) return flask.abort(411) if usr.disabled: journal.entry( journal.USER_WG_FAILURE, usr.journal_data, remote_address=remote_addr, event_long='User disabled', ) return flask.abort(403) cipher_data64 = flask.request.json.get('data') box_nonce64 = flask.request.json.get('nonce') public_key64 = flask.request.json.get('public_key') signature64 = flask.request.json.get('signature') auth_string = '&'.join([ usr.sync_token, auth_timestamp, auth_nonce, flask.request.method, flask.request.path, cipher_data64, box_nonce64, public_key64, signature64]) if len(auth_string) > AUTH_SIG_STRING_MAX_LEN: journal.entry( journal.USER_WG_FAILURE, usr.journal_data, remote_address=remote_addr, event_long='Auth string len limit exceeded', ) return flask.abort(414) auth_test_signature = base64.b64encode(hmac.new( usr.sync_secret.encode(), auth_string.encode(), hashlib.sha512).digest()).decode() if not utils.const_compare(auth_signature, auth_test_signature): journal.entry( journal.USER_WG_FAILURE, usr.journal_data, remote_address=remote_addr, event_long='Auth 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_WG_FAILURE, usr.journal_data, remote_address=remote_addr, event_long='Duplicate nonce', ) return flask.abort(409) data_hash = hashlib.sha512( '&'.join([cipher_data64, box_nonce64, public_key64]).encode(), ).digest() try: usr.verify_sig( data_hash, base64.b64decode(signature64), ) except InvalidSignature: journal.entry( journal.USER_WG_FAILURE, usr.journal_data, remote_address=remote_addr, event_long='Invalid rsa signature', ) return flask.abort(412) svr = usr.get_server(server_id) sender_pub_key = nacl.public.PublicKey( base64.b64decode(public_key64)) box_nonce = base64.b64decode(box_nonce64) priv_key = nacl.public.PrivateKey( base64.b64decode(svr.auth_box_private_key)) cipher_data = base64.b64decode(cipher_data64) nacl_box = nacl.public.Box(priv_key, sender_pub_key) plaintext = nacl_box.decrypt(cipher_data, box_nonce).decode() try: nonces_collection.insert({ 'token': auth_token, 'nonce': box_nonce64, 'timestamp': utils.now(), }) except pymongo.errors.DuplicateKeyError: journal.entry( journal.USER_WG_FAILURE, usr.journal_data, remote_address=remote_addr, event_long='Duplicate secondary nonce', ) return flask.abort(415) key_data = json.loads(plaintext) client_platform = utils.filter_str(key_data['platform']) client_device_id = utils.filter_str(key_data['device_id']) client_device_name = utils.filter_str(key_data['device_name']) client_mac_addr = utils.filter_str(key_data['mac_addr']) client_mac_addrs = key_data['mac_addrs'] if client_mac_addrs: client_mac_addrs = [utils.filter_str(x) for x in client_mac_addrs] else: client_mac_addrs = None client_auth_token = key_data['token'] client_auth_nonce = utils.filter_str(key_data['nonce']) client_auth_password = key_data['password'] client_auth_timestamp = int(key_data['timestamp']) client_wg_public_key = key_data['wg_public_key'] if len(client_wg_public_key) < 32: journal.entry( journal.USER_WG_FAILURE, usr.journal_data, remote_address=remote_addr, event_long='Public key too short', ) return flask.abort(416) try: client_wg_public_key = base64.b64decode(client_wg_public_key) if len(client_wg_public_key) != 32: raise ValueError('Invalid length') client_wg_public_key = base64.b64encode(client_wg_public_key) except: journal.entry( journal.USER_WG_FAILURE, usr.journal_data, remote_address=remote_addr, event_long='Public key invalid', ) return flask.abort(417) instance = server.get_instance(server_id) if not instance or instance.state != 'running': return flask.abort(429) if not instance.server.wg: return flask.abort(429) wg_keys_collection = mongo.get_collection('wg_keys') try: wg_keys_collection.insert({ '_id': client_wg_public_key, 'timestamp': utils.now(), }) except pymongo.errors.DuplicateKeyError: journal.entry( journal.USER_WG_FAILURE, usr.journal_data, remote_address=remote_addr, wg_public_key=client_wg_public_key, event_long='Duplicate wg public key', ) return flask.abort(413) clients = instance.instance_com.clients event = threading.Event() send_data = { 'allow': None, 'configuration': None, 'reason': None, } def callback(allow, data): send_data['allow'] = allow if allow: send_data['configuration'] = data else: send_data['reason'] = data event.set() clients.connect_wg( user=usr, org=org, wg_public_key=client_wg_public_key, auth_password=client_auth_password, auth_token=client_auth_token, auth_nonce=client_auth_nonce, auth_timestamp=client_auth_timestamp, platform=client_platform, device_id=client_device_id, device_name=client_device_name, mac_addr=client_mac_addr, mac_addrs=client_mac_addrs, remote_ip=remote_addr, connect_callback=callback, ) event.wait() send_nonce = nacl.utils.random(nacl.public.Box.NONCE_SIZE) nacl_box = nacl.public.Box(priv_key, sender_pub_key) send_cipher_data = nacl_box.encrypt( json.dumps(send_data).encode(), send_nonce) send_cipher_data = send_cipher_data[nacl.public.Box.NONCE_SIZE:] send_nonce64 = base64.b64encode(send_nonce).decode() send_cipher_data64 = base64.b64encode(send_cipher_data).decode() usr.audit_event('user_profile', 'User retrieved wg public key from pritunl client', remote_addr=remote_addr, ) journal.entry( journal.USER_WG_SUCCESS, usr.journal_data, remote_address=remote_addr, event_long='User retrieved wg public key from pritunl client', ) sync_signature = base64.b64encode(hmac.new( usr.sync_secret.encode(), (send_cipher_data64 + '&' + send_nonce64).encode(), hashlib.sha512).digest()).decode() return utils.jsonify({ 'data': send_cipher_data64, 'nonce': send_nonce64, 'signature': sync_signature, })
def server_put_post(server_id=None): used_resources = server.get_used_resources(server_id) network_used = used_resources['networks'] interface_used = used_resources['interfaces'] port_used = used_resources['ports'] name = None name_def = False if 'name' in flask.request.json: name_def = True name = utils.filter_str(flask.request.json['name']) network = None network_def = False if 'network' in flask.request.json: network_def = True network = flask.request.json['network'] if network not in settings.vpn.safe_pub_subnets: network_split = network.split('/') if len(network_split) != 2: return _network_invalid() address = network_split[0].split('.') if len(address) != 4: return _network_invalid() for i, value in enumerate(address): try: address[i] = int(value) except ValueError: return _network_invalid() try: subnet = int(network_split[1]) except ValueError: return _network_invalid() if address[0] == 10: if address[1] < 0 or address[1] > 255: return _network_invalid() if subnet not in (8, 16, 24): return _network_invalid() elif address[0] == 172: if address[1] < 16 or address[1] > 31: return _network_invalid() if subnet not in (16, 24): return _network_invalid() elif address[0] == 192 and address[1] == 168: if subnet != 24: return _network_invalid() else: return _network_invalid() if address[2] < 0 or address[2] > 255: return _network_invalid() if address[3] != 0: return _network_invalid() interface = None interface_def = False if 'interface' in flask.request.json: interface_def = True interface = flask.request.json['interface'] if not re.match('^[a-z0-9]+$', interface): return _interface_invalid() if interface[:3] != 'tun': return _interface_invalid() try: interface_num = int(interface[3:]) except ValueError: return _interface_invalid() if interface_num > 64: return _interface_invalid() interface = interface[:3] + str(interface_num) protocol = 'udp' protocol_def = False if 'protocol' in flask.request.json: protocol_def = True protocol = flask.request.json['protocol'].lower() if protocol not in ('udp', 'tcp'): return utils.jsonify( { 'error': PROTOCOL_INVALID, 'error_msg': PROTOCOL_INVALID_MSG, }, 400) port = None port_def = False if 'port' in flask.request.json: port_def = True port = flask.request.json['port'] try: port = int(port) except ValueError: return _port_invalid() if port < 1 or port > 65535: return _port_invalid() dh_param_bits = None dh_param_bits_def = False if 'dh_param_bits' in flask.request.json: dh_param_bits_def = True dh_param_bits = flask.request.json['dh_param_bits'] try: dh_param_bits = int(dh_param_bits) except ValueError: return _dh_param_bits_invalid() if dh_param_bits not in VALID_DH_PARAM_BITS: return _dh_param_bits_invalid() mode = None mode_def = False if 'mode' in flask.request.json: mode_def = True mode = flask.request.json['mode'] if mode not in (ALL_TRAFFIC, LOCAL_TRAFFIC, VPN_TRAFFIC): return utils.jsonify( { 'error': MODE_INVALID, 'error_msg': MODE_INVALID_MSG, }, 400) local_networks = None local_networks_def = False if 'local_networks' in flask.request.json: local_networks_def = True local_networks = flask.request.json['local_networks'] or [] for local_network in local_networks: local_network_split = local_network.split('/') if len(local_network_split) != 2: return _local_network_invalid() address = local_network_split[0].split('.') if len(address) != 4: return _local_network_invalid() for i, value in enumerate(address): try: address[i] = int(value) except ValueError: return _local_network_invalid() if address[0] > 255 or address[0] < 0 or \ address[1] > 255 or address[1] < 0 or \ address[2] > 255 or address[2] < 0 or \ address[3] > 254 or address[3] < 0: return _local_network_invalid() try: subnet = int(local_network_split[1]) except ValueError: return _local_network_invalid() if subnet < 8 or subnet > 30: return _local_network_invalid() dns_servers = None dns_servers_def = False if 'dns_servers' in flask.request.json: dns_servers_def = True dns_servers = flask.request.json['dns_servers'] or [] for dns_server in dns_servers: if not re.match(IP_REGEX, dns_server): return _dns_server_invalid() search_domain = None search_domain_def = False if 'search_domain' in flask.request.json: search_domain_def = True search_domain = utils.filter_str(flask.request.json['search_domain']) public_address = None public_address_def = False if 'public_address' in flask.request.json: public_address_def = True public_address = utils.filter_str(flask.request.json['public_address']) debug = False debug_def = False if 'debug' in flask.request.json: debug_def = True debug = True if flask.request.json['debug'] else False otp_auth = False otp_auth_def = False if 'otp_auth' in flask.request.json: otp_auth_def = True otp_auth = True if flask.request.json['otp_auth'] else False lzo_compression = False lzo_compression_def = False if 'lzo_compression' in flask.request.json: lzo_compression_def = True lzo_compression = True if flask.request.json[ 'lzo_compression'] else False if not server_id: if not name_def: return utils.jsonify( { 'error': MISSING_PARAMS, 'error_msg': MISSING_PARAMS_MSG, }, 400) if not network_def: network_def = True for i in xrange(5000): rand_network = '10.%s.%s.0/24' % (random.randint( 15, 250), random.randint(15, 250)) if rand_network not in network_used: network = rand_network break if not network: return utils.jsonify( { 'error': NETWORK_IN_USE, 'error_msg': NETWORK_IN_USE_MSG, }, 400) if not interface_def: interface_def = True for i in xrange(64): rand_interface = 'tun%s' % i if rand_interface not in interface_used: interface = rand_interface break if not interface: return utils.jsonify( { 'error': INTERFACE_IN_USE, 'error_msg': INTERFACE_IN_USE_MSG, }, 400) if not port_def: port_def = True rand_ports = range(10000, 19999) random.shuffle(rand_ports) for rand_port in rand_ports: if '%s%s' % (rand_port, protocol) not in port_used: port = rand_port break if not port: return utils.jsonify( { 'error': PORT_PROTOCOL_IN_USE, 'error_msg': PORT_PROTOCOL_IN_USE_MSG, }, 400) if not dh_param_bits_def: dh_param_bits_def = True dh_param_bits = settings.vpn.default_dh_param_bits if not mode_def: mode_def = True if local_networks_def and local_networks: mode = LOCAL_TRAFFIC else: mode = ALL_TRAFFIC if not public_address_def: public_address_def = True public_address = settings.local.public_ip if network_def: if network in network_used: return utils.jsonify( { 'error': NETWORK_IN_USE, 'error_msg': NETWORK_IN_USE_MSG, }, 400) if interface_def: if interface in interface_used: return utils.jsonify( { 'error': INTERFACE_IN_USE, 'error_msg': INTERFACE_IN_USE_MSG, }, 400) if port_def: if '%s%s' % (port, protocol) in port_used: return utils.jsonify( { 'error': PORT_PROTOCOL_IN_USE, 'error_msg': PORT_PROTOCOL_IN_USE_MSG, }, 400) if not server_id: svr = server.new_server( name=name, network=network, interface=interface, port=port, protocol=protocol, dh_param_bits=dh_param_bits, mode=mode, local_networks=local_networks, dns_servers=dns_servers, search_domain=search_domain, public_address=public_address, otp_auth=otp_auth, lzo_compression=lzo_compression, debug=debug, ) else: svr = server.get_server(id=server_id) if svr.status: return utils.jsonify( { 'error': SERVER_NOT_OFFLINE, 'error_msg': SERVER_NOT_OFFLINE_SETTINGS_MSG, }, 400) if name_def: svr.name = name if network_def: svr.network = network if interface_def: svr.interface = interface if port_def: svr.port = port if protocol_def: svr.protocol = protocol if dh_param_bits_def and svr.dh_param_bits != dh_param_bits: svr.dh_param_bits = dh_param_bits svr.generate_dh_param() if mode_def: svr.mode = mode if local_networks_def: svr.local_networks = local_networks if dns_servers_def: svr.dns_servers = dns_servers if search_domain_def: svr.search_domain = search_domain if public_address_def: svr.public_address = public_address if otp_auth_def: svr.otp_auth = otp_auth if lzo_compression_def: svr.lzo_compression = lzo_compression if debug_def: svr.debug = debug svr.commit(svr.changed) logger.LogEntry(message='Created server "%s".' % svr.name) event.Event(type=SERVERS_UPDATED) for org in svr.iter_orgs(): event.Event(type=USERS_UPDATED, resource_id=org.id) return utils.jsonify(svr.dict())
def server_put_post(server_id=None): if settings.app.demo_mode: return utils.demo_blocked() used_resources = server.get_used_resources(server_id) network_used = used_resources['networks'] port_used = used_resources['ports'] name = None name_def = False if 'name' in flask.request.json: name_def = True name = utils.filter_str(flask.request.json['name']) network = None network_def = False if 'network' in flask.request.json: network_def = True network = flask.request.json['network'] try: if not _check_network_private(network): return _network_invalid() except (ipaddress.AddressValueError, ValueError): return _network_invalid() network_mode = None network_mode_def = False if 'network_mode' in flask.request.json: network_mode_def = True network_mode = flask.request.json['network_mode'] network_start = None network_start_def = False if 'network_start' in flask.request.json: network_start_def = True network_start = flask.request.json['network_start'] network_end = None network_end_def = False if 'network_end' in flask.request.json: network_end_def = True network_end = flask.request.json['network_end'] ipv6 = None ipv6_def = False if 'ipv6' in flask.request.json: ipv6_def = True ipv6 = True if flask.request.json['ipv6'] else False ipv6_firewall = None ipv6_firewall_def = False if 'ipv6_firewall' in flask.request.json: ipv6_firewall_def = True ipv6_firewall = True if flask.request.json['ipv6_firewall'] else False bind_address = None bind_address_def = False if 'bind_address' in flask.request.json: bind_address_def = True bind_address = utils.filter_str(flask.request.json['bind_address']) protocol = 'udp' protocol_def = False if 'protocol' in flask.request.json: protocol_def = True protocol = flask.request.json['protocol'].lower() if protocol not in ('udp', 'tcp'): return utils.jsonify({ 'error': PROTOCOL_INVALID, 'error_msg': PROTOCOL_INVALID_MSG, }, 400) port = None port_def = False if 'port' in flask.request.json: port_def = True port = flask.request.json['port'] try: port = int(port) except ValueError: return _port_invalid() if port < 1 or port > 65535: return _port_invalid() dh_param_bits = None dh_param_bits_def = False if flask.request.json.get('dh_param_bits'): dh_param_bits_def = True dh_param_bits = flask.request.json['dh_param_bits'] try: dh_param_bits = int(dh_param_bits) except ValueError: return _dh_param_bits_invalid() if dh_param_bits not in VALID_DH_PARAM_BITS: return _dh_param_bits_invalid() mode = None mode_def = False if 'mode' in flask.request.json: mode_def = True mode = flask.request.json['mode'] if mode not in (ALL_TRAFFIC, LOCAL_TRAFFIC, VPN_TRAFFIC): return utils.jsonify({ 'error': MODE_INVALID, 'error_msg': MODE_INVALID_MSG, }, 400) multi_device = False multi_device_def = False if 'multi_device' in flask.request.json: multi_device_def = True multi_device = True if flask.request.json['multi_device'] else False local_networks = None local_networks_def = False if 'local_networks' in flask.request.json: local_networks_def = True local_networks = flask.request.json['local_networks'] or [] for local_network in local_networks: try: ipaddress.IPNetwork(local_network) except (ipaddress.AddressValueError, ValueError): return _local_network_invalid() dns_servers = None dns_servers_def = False if 'dns_servers' in flask.request.json: dns_servers_def = True dns_servers = flask.request.json['dns_servers'] or [] for dns_server in dns_servers: try: ipaddress.IPAddress(dns_server) except (ipaddress.AddressValueError, ValueError): return _dns_server_invalid() search_domain = None search_domain_def = False if 'search_domain' in flask.request.json: search_domain_def = True search_domain = utils.filter_str(flask.request.json['search_domain']) inter_client = True inter_client_def = False if 'inter_client' in flask.request.json: inter_client_def = True inter_client = True if flask.request.json['inter_client'] else False ping_interval = None ping_interval_def = False if 'ping_interval' in flask.request.json: ping_interval_def = True ping_interval = flask.request.json['ping_interval'] if ping_interval: ping_interval = int(ping_interval) if not ping_interval: ping_interval = 10 ping_timeout = None ping_timeout_def = False if 'ping_timeout' in flask.request.json: ping_timeout_def = True ping_timeout = flask.request.json['ping_timeout'] if ping_timeout: ping_timeout = int(ping_timeout) if not ping_timeout: ping_timeout = 60 link_ping_interval = None link_ping_interval_def = False if 'link_ping_interval' in flask.request.json: link_ping_interval_def = True link_ping_interval = flask.request.json['link_ping_interval'] if link_ping_interval: link_ping_interval = int(link_ping_interval) if not link_ping_interval: link_ping_interval = 1 link_ping_timeout = None link_ping_timeout_def = False if 'link_ping_timeout' in flask.request.json: link_ping_timeout_def = True link_ping_timeout = flask.request.json['link_ping_timeout'] if link_ping_timeout: link_ping_timeout = int(link_ping_timeout) if not link_ping_timeout: link_ping_timeout = 5 max_clients = None max_clients_def = False if 'max_clients' in flask.request.json: max_clients_def = True max_clients = flask.request.json['max_clients'] if max_clients: max_clients = int(max_clients) if not max_clients: max_clients = 1024 replica_count = None replica_count_def = False if 'replica_count' in flask.request.json: replica_count_def = True replica_count = flask.request.json['replica_count'] if replica_count: replica_count = int(replica_count) if not replica_count: replica_count = 1 dns_mapping = False dns_mapping_def = False if 'dns_mapping' in flask.request.json: dns_mapping_def = True dns_mapping = True if flask.request.json['dns_mapping'] else False debug = False debug_def = False if 'debug' in flask.request.json: debug_def = True debug = True if flask.request.json['debug'] else False otp_auth = False otp_auth_def = False if 'otp_auth' in flask.request.json: otp_auth_def = True otp_auth = True if flask.request.json['otp_auth'] else False lzo_compression = False lzo_compression_def = False if 'lzo_compression' in flask.request.json: lzo_compression_def = True lzo_compression = True if flask.request.json[ 'lzo_compression'] else False cipher = None cipher_def = False if 'cipher' in flask.request.json: cipher_def = True cipher = flask.request.json['cipher'] if cipher not in CIPHERS: return utils.jsonify({ 'error': CIPHER_INVALID, 'error_msg': CIPHER_INVALID_MSG, }, 400) hash = None hash_def = False if 'hash' in flask.request.json: hash_def = True hash = flask.request.json['hash'] if hash not in HASHES: return utils.jsonify({ 'error': HASH_INVALID, 'error_msg': HASH_INVALID_MSG, }, 400) jumbo_frames = False jumbo_frames_def = False if 'jumbo_frames' in flask.request.json: jumbo_frames_def = True jumbo_frames = True if flask.request.json[ 'jumbo_frames'] else False if not server_id: if not name_def: return utils.jsonify({ 'error': MISSING_PARAMS, 'error_msg': MISSING_PARAMS_MSG, }, 400) if network_def and network_mode == BRIDGE and \ (not network_start or not network_end): return utils.jsonify({ 'error': MISSING_PARAMS, 'error_msg': MISSING_PARAMS_MSG, }, 400) if not network_def: network_def = True rand_range = range(215, 250) rand_range_low = range(15, 215) random.shuffle(rand_range) random.shuffle(rand_range_low) rand_range += rand_range_low for i in rand_range: rand_network = '192.168.%s.0/24' % i if not _check_network_overlap(rand_network, network_used): network = rand_network break if not network: return utils.jsonify({ 'error': NETWORK_IN_USE, 'error_msg': NETWORK_IN_USE_MSG, }, 400) if not port_def: port_def = True rand_ports = range(10000, 19999) random.shuffle(rand_ports) for rand_port in rand_ports: if '%s%s' % (rand_port, protocol) not in port_used: port = rand_port break if not port: return utils.jsonify({ 'error': PORT_PROTOCOL_IN_USE, 'error_msg': PORT_PROTOCOL_IN_USE_MSG, }, 400) if not dh_param_bits_def: dh_param_bits_def = True dh_param_bits = settings.vpn.default_dh_param_bits if not mode_def: mode_def = True if local_networks_def and local_networks: mode = LOCAL_TRAFFIC else: mode = ALL_TRAFFIC if network_def: if _check_network_overlap(network, network_used): return utils.jsonify({ 'error': NETWORK_IN_USE, 'error_msg': NETWORK_IN_USE_MSG, }, 400) if port_def: if '%s%s' % (port, protocol) in port_used: return utils.jsonify({ 'error': PORT_PROTOCOL_IN_USE, 'error_msg': PORT_PROTOCOL_IN_USE_MSG, }, 400) if not server_id: if network_mode == BRIDGE: if not _check_network_range(network, network_start, network_end): return utils.jsonify({ 'error': BRIDGE_NETWORK_INVALID, 'error_msg': BRIDGE_NETWORK_INVALID_MSG, }, 400) if ipv6: return utils.jsonify({ 'error': IPV6_BRIDGED_INVALID, 'error_msg': IPV6_BRIDGED_INVALID_MSG, }, 400) svr = server.new_server( name=name, network=network, network_mode=network_mode, network_start=network_start, network_end=network_end, ipv6=ipv6, ipv6_firewall=ipv6_firewall, bind_address=bind_address, port=port, protocol=protocol, dh_param_bits=dh_param_bits, mode=mode, multi_device=multi_device, local_networks=local_networks, dns_servers=dns_servers, search_domain=search_domain, otp_auth=otp_auth, cipher=cipher, hash=hash, jumbo_frames=jumbo_frames, lzo_compression=lzo_compression, inter_client=inter_client, ping_interval=ping_interval, ping_timeout=ping_timeout, link_ping_interval=link_ping_interval, link_ping_timeout=link_ping_timeout, max_clients=max_clients, replica_count=replica_count, dns_mapping=dns_mapping, debug=debug, ) svr.add_host(settings.local.host_id) svr.commit() else: svr = server.get_by_id(server_id) if svr.status == ONLINE: return utils.jsonify({ 'error': SERVER_NOT_OFFLINE, 'error_msg': SERVER_NOT_OFFLINE_SETTINGS_MSG, }, 400) for link_svr in svr.iter_links(fields=('status',)): if link_svr.status == ONLINE: return utils.jsonify({ 'error': SERVER_LINKS_NOT_OFFLINE, 'error_msg': SERVER_LINKS_NOT_OFFLINE_SETTINGS_MSG, }, 400) if name_def: svr.name = name if network_def: svr.network = network if network_start_def: svr.network_start = network_start if network_end_def: svr.network_end = network_end if ipv6_def: svr.ipv6 = ipv6 if ipv6_firewall_def: svr.ipv6_firewall = ipv6_firewall if network_mode_def: if network_mode == BRIDGE and ( not network_start or not network_end): return utils.jsonify({ 'error': MISSING_PARAMS, 'error_msg': MISSING_PARAMS_MSG, }, 400) svr.network_mode = network_mode if bind_address_def: svr.bind_address = bind_address if port_def: svr.port = port if protocol_def: svr.protocol = protocol if dh_param_bits_def and svr.dh_param_bits != dh_param_bits: svr.dh_param_bits = dh_param_bits svr.generate_dh_param() if mode_def: svr.mode = mode if multi_device_def: svr.multi_device = multi_device if local_networks_def: svr.local_networks = local_networks if dns_servers_def: svr.dns_servers = dns_servers if search_domain_def: svr.search_domain = search_domain if otp_auth_def: svr.otp_auth = otp_auth if cipher_def: svr.cipher = cipher if hash_def: svr.hash = hash if jumbo_frames_def: svr.jumbo_frames = jumbo_frames if lzo_compression_def: svr.lzo_compression = lzo_compression if inter_client_def: svr.inter_client = inter_client if ping_interval_def: svr.ping_interval = ping_interval if ping_timeout_def: svr.ping_timeout = ping_timeout if link_ping_interval_def: svr.link_ping_interval = link_ping_interval if link_ping_timeout_def: svr.link_ping_timeout = link_ping_timeout if max_clients_def: svr.max_clients = max_clients if replica_count_def: svr.replica_count = replica_count if dns_mapping_def: svr.dns_mapping = dns_mapping if debug_def: svr.debug = debug if svr.network_mode == BRIDGE: if not _check_network_range(svr.network, svr.network_start, svr.network_end): return utils.jsonify({ 'error': BRIDGE_NETWORK_INVALID, 'error_msg': BRIDGE_NETWORK_INVALID_MSG, }, 400) if svr.ipv6: return utils.jsonify({ 'error': IPV6_BRIDGED_INVALID, 'error_msg': IPV6_BRIDGED_INVALID_MSG, }, 400) if svr.links and svr.replica_count > 1: return utils.jsonify({ 'error': SERVER_LINKS_AND_REPLICA, 'error_msg': SERVER_LINKS_AND_REPLICA_MSG, }, 400) svr.commit(svr.changed) logger.LogEntry(message='Created server "%s".' % svr.name) event.Event(type=SERVERS_UPDATED) for org in svr.iter_orgs(): event.Event(type=USERS_UPDATED, resource_id=org.id) return utils.jsonify(svr.dict())
def server_output_delete(server_id): svr = server.get_server(id=server_id) svr.output.clear_output() return utils.jsonify({})
def _port_invalid(): return utils.jsonify({ 'error': PORT_INVALID, 'error_msg': PORT_INVALID_MSG, }, 400)
def server_output_get(server_id): svr = server.get_server(id=server_id) return utils.jsonify({ 'id': svr.id, 'output': svr.output.get_output(), })
def _dh_param_bits_invalid(): return utils.jsonify({ 'error': DH_PARAM_BITS_INVALID, 'error_msg': DH_PARAM_BITS_INVALID_MSG, }, 400)
def auth_session_post(): username = utils.json_filter_str('username')[:128].lower() password = utils.json_str('password')[:128] otp_code = utils.json_opt_filter_str('otp_code')[:128] yubico_key = utils.json_opt_filter_str('yubico_key')[:128] remote_addr = utils.get_remote_addr() time.sleep(random.randint(50, 100) / 1000.) admin = auth.get_by_username(username) if not admin: if settings.app.sso and RADIUS_AUTH in settings.app.sso: return _auth_radius(username, password, remote_addr) time.sleep(random.randint(0, 100) / 1000.) return _auth_plugin(username, password, remote_addr) if (not otp_code and admin.otp_auth) or \ (not yubico_key and admin.yubikey_id): return utils.jsonify( { 'error': AUTH_OTP_REQUIRED, 'error_msg': AUTH_OTP_REQUIRED_MSG, 'otp_auth': admin.otp_auth, 'yubico_auth': bool(admin.yubikey_id), }, 402) if not limiter.auth_check(admin.id): journal.entry( journal.ADMIN_AUTH_FAILURE, admin.journal_data, remote_address=remote_addr, reason=journal.ADMIN_AUTH_REASON_RATE_LIMIT, reason_long='Too many authentication attempts', ) return utils.jsonify( { 'error': AUTH_TOO_MANY, 'error_msg': AUTH_TOO_MANY_MSG, }, 400) if not admin.auth_check(password, otp_code, yubico_key, remote_addr): time.sleep(random.randint(0, 100) / 1000.) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) flask.session['session_id'] = admin.new_session() flask.session['admin_id'] = str(admin.id) flask.session['timestamp'] = int(utils.time_now()) if not settings.app.server_ssl: flask.session['source'] = remote_addr journal.entry( journal.ADMIN_SESSION_START, admin.journal_data, remote_address=remote_addr, session_id=flask.session['session_id'], ) utils.set_flask_sig() return utils.jsonify({ 'authenticated': True, 'default': admin.default or False, })
def _local_network_invalid(): return utils.jsonify({ 'error': LOCAL_NETWORK_INVALID, 'error_msg': LOCAL_NETWORK_INVALID_MSG, }, 400)
def _auth_radius(username, password, remote_addr): sso_mode = settings.app.sso valid, org_names, groups = sso.verify_radius(username, password) if not valid: journal.entry( journal.SSO_AUTH_FAILURE, user_name=username, remote_address=remote_addr, reason=journal.SSO_AUTH_REASON_RADIUS_FAILED, reason_long='Radius authentication failed', ) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) org_id = settings.app.sso_org if org_names: not_found = False for org_name in org_names: org = organization.get_by_name(org_name, fields=('_id')) if org: not_found = False org_id = org.id break else: not_found = True if not_found: logger.warning( 'Supplied org names do not exists', 'sso', sso_type='radius', user_name=username, org_names=org_names, ) valid, org_id_new, groups2 = sso.plugin_sso_authenticate( sso_type='radius', user_name=username, user_email=None, remote_ip=utils.get_remote_addr(), ) if valid: org_id = org_id_new or org_id else: journal.entry( journal.SSO_AUTH_FAILURE, user_name=username, remote_address=remote_addr, reason=journal.SSO_AUTH_REASON_PLUGIN_FAILED, reason_long='Radius plugin authentication failed', ) logger.error( 'Radius plugin authentication not valid', 'sso', username=username, ) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) groups = ((groups or set()) | (groups2 or set())) or None if DUO_AUTH in sso_mode: try: duo_auth = sso.Duo( username=username, factor=settings.app.sso_duo_mode, remote_ip=utils.get_remote_addr(), auth_type='Key', ) valid = duo_auth.authenticate() except InvalidUser: logger.error( 'Duo authentication username not valid', 'sso', username=username, ) journal.entry( journal.SSO_AUTH_FAILURE, user_name=username, remote_address=remote_addr, reason=journal.SSO_AUTH_REASON_DUO_FAILED, reason_long='Duo authentication invalid username', ) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) if valid: valid, org_id_new, groups2 = sso.plugin_sso_authenticate( sso_type='duo', user_name=username, user_email=None, remote_ip=utils.get_remote_addr(), ) if valid: org_id = org_id_new or org_id else: journal.entry( journal.SSO_AUTH_FAILURE, user_name=username, remote_address=remote_addr, reason=journal.SSO_AUTH_REASON_PLUGIN_FAILED, reason_long='Duo plugin authentication failed', ) logger.error( 'Duo plugin authentication not valid', 'sso', username=username, ) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) groups = ((groups or set()) | (groups2 or set())) or None else: logger.error( 'Duo authentication not valid', 'sso', username=username, ) journal.entry( journal.SSO_AUTH_FAILURE, user_name=username, remote_address=remote_addr, reason=journal.SSO_AUTH_REASON_DUO_FAILED, reason_long='Duo authentication failed', ) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) groups = ((groups or set()) | (groups2 or set())) or None org = organization.get_by_id(org_id) if not org: return flask.abort(405) usr = org.find_user(name=username) if not usr: usr = org.new_user(name=username, type=CERT_CLIENT, auth_type=sso_mode, groups=list(groups) if groups else None) usr.audit_event( 'user_created', 'User created with single sign-on', remote_addr=remote_addr, ) journal.entry( journal.USER_CREATE, usr.journal_data, event_long='User created with single sign-on', remote_address=remote_addr, ) event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) else: if usr.disabled: return utils.jsonify( { 'error': AUTH_DISABLED, 'error_msg': AUTH_DISABLED_MSG, }, 403) if groups and groups - set(usr.groups or []): usr.groups = list(set(usr.groups or []) | groups) usr.commit('groups') if usr.auth_type != sso_mode: usr.auth_type = sso_mode usr.set_pin(None) usr.commit(('auth_type', 'pin')) key_link = org.create_user_key_link(usr.id, one_time=True) journal.entry( journal.SSO_AUTH_SUCCESS, usr.journal_data, key_id_hash=hashlib.md5(key_link['id']).hexdigest(), remote_address=remote_addr, ) usr.audit_event( 'user_profile', 'User profile viewed from single sign-on', remote_addr=utils.get_remote_addr(), ) journal.entry( journal.USER_PROFILE_SUCCESS, usr.journal_data, event_long='User profile viewed from single sign-on', remote_address=remote_addr, ) return utils.jsonify( { 'redirect': utils.get_url_root() + key_link['view_url'], }, 202)
def settings_put(): if settings.app.demo_mode: return utils.demo_blocked() org_event = False admin_event = False admin = flask.g.administrator changes = set() settings_commit = False update_server = False update_acme = False update_cert = False if 'username' in flask.request.json and flask.request.json['username']: username = utils.filter_str( flask.request.json['username']).lower() if username != admin.username: changes.add('username') admin.username = username if 'password' in flask.request.json and flask.request.json['password']: password = flask.request.json['password'] changes.add('password') admin.password = password if 'server_cert' in flask.request.json: settings_commit = True server_cert = flask.request.json['server_cert'] if server_cert: server_cert = server_cert.strip() else: server_cert = None if server_cert != settings.app.server_cert: update_server = True settings.app.server_cert = server_cert if 'server_key' in flask.request.json: settings_commit = True server_key = flask.request.json['server_key'] if server_key: server_key = server_key.strip() else: server_key = None if server_key != settings.app.server_key: update_server = True settings.app.server_key = server_key if 'server_port' in flask.request.json: settings_commit = True server_port = flask.request.json['server_port'] if not server_port: server_port = 443 try: server_port = int(server_port) if server_port < 1 or server_port > 65535: raise ValueError('Port invalid') except ValueError: return utils.jsonify({ 'error': PORT_INVALID, 'error_msg': PORT_INVALID_MSG, }, 400) if settings.app.redirect_server and server_port == 80: return utils.jsonify({ 'error': PORT_RESERVED, 'error_msg': PORT_RESERVED_MSG, }, 400) if server_port != settings.app.server_port: update_server = True settings.app.server_port = server_port if 'acme_domain' in flask.request.json: settings_commit = True acme_domain = utils.filter_str( flask.request.json['acme_domain'] or None) if acme_domain: acme_domain = acme_domain.replace('https://', '') acme_domain = acme_domain.replace('http://', '') acme_domain = acme_domain.replace('/', '') if acme_domain != settings.app.acme_domain: if not acme_domain: settings.app.acme_key = None settings.app.acme_timestamp = None settings.app.server_key = None settings.app.server_cert = None update_server = True update_cert = True else: update_acme = True settings.app.acme_domain = acme_domain if 'auditing' in flask.request.json: settings_commit = True auditing = flask.request.json['auditing'] or None if settings.app.auditing != auditing: if not flask.g.administrator.super_user: return utils.jsonify({ 'error': REQUIRES_SUPER_USER, 'error_msg': REQUIRES_SUPER_USER_MSG, }, 400) admin_event = True org_event = True settings.app.auditing = auditing if 'monitoring' in flask.request.json: settings_commit = True monitoring = flask.request.json['monitoring'] or None settings.app.monitoring = monitoring if 'influxdb_uri' in flask.request.json: settings_commit = True influxdb_uri = flask.request.json['influxdb_uri'] or None settings.app.influxdb_uri = influxdb_uri if 'email_from' in flask.request.json: settings_commit = True email_from = flask.request.json['email_from'] or None if email_from != settings.app.email_from: changes.add('smtp') settings.app.email_from = email_from if 'email_server' in flask.request.json: settings_commit = True email_server = flask.request.json['email_server'] or None if email_server != settings.app.email_server: changes.add('smtp') settings.app.email_server = email_server if 'email_username' in flask.request.json: settings_commit = True email_username = flask.request.json['email_username'] or None if email_username != settings.app.email_username: changes.add('smtp') settings.app.email_username = email_username if 'email_password' in flask.request.json: settings_commit = True email_password = flask.request.json['email_password'] or None if email_password != settings.app.email_password: changes.add('smtp') settings.app.email_password = email_password if 'pin_mode' in flask.request.json: settings_commit = True pin_mode = flask.request.json['pin_mode'] or None if pin_mode != settings.user.pin_mode: changes.add('pin_mode') settings.user.pin_mode = pin_mode if 'sso' in flask.request.json: org_event = True settings_commit = True sso = flask.request.json['sso'] or None if sso != settings.app.sso: changes.add('sso') settings.app.sso = sso if 'sso_match' in flask.request.json: settings_commit = True sso_match = flask.request.json['sso_match'] or None if sso_match != settings.app.sso_match: changes.add('sso') if isinstance(sso_match, list): settings.app.sso_match = sso_match else: settings.app.sso_match = None if 'sso_google_key' in flask.request.json: settings_commit = True sso_google_key = flask.request.json['sso_google_key'] or None if sso_google_key != settings.app.sso_google_key: changes.add('sso') settings.app.sso_google_key = sso_google_key if 'sso_google_email' in flask.request.json: settings_commit = True sso_google_email = flask.request.json['sso_google_email'] or None if sso_google_email != settings.app.sso_google_email: changes.add('sso') settings.app.sso_google_email = sso_google_email if 'sso_duo_token' in flask.request.json: settings_commit = True sso_duo_token = flask.request.json['sso_duo_token'] or None if sso_duo_token != settings.app.sso_duo_token: changes.add('sso') settings.app.sso_duo_token = sso_duo_token if 'sso_duo_secret' in flask.request.json: settings_commit = True sso_duo_secret = flask.request.json['sso_duo_secret'] or None if sso_duo_secret != settings.app.sso_duo_secret: changes.add('sso') settings.app.sso_duo_secret = sso_duo_secret if 'sso_duo_host' in flask.request.json: settings_commit = True sso_duo_host = flask.request.json['sso_duo_host'] or None if sso_duo_host != settings.app.sso_duo_host: changes.add('sso') settings.app.sso_duo_host = sso_duo_host if 'sso_duo_mode' in flask.request.json: settings_commit = True sso_duo_mode = flask.request.json['sso_duo_mode'] or None if sso_duo_mode != settings.app.sso_duo_mode: changes.add('sso') settings.app.sso_duo_mode = sso_duo_mode if 'sso_radius_secret' in flask.request.json: settings_commit = True sso_radius_secret = flask.request.json['sso_radius_secret'] or None if sso_radius_secret != settings.app.sso_radius_secret: changes.add('sso') settings.app.sso_radius_secret = sso_radius_secret if 'sso_radius_host' in flask.request.json: settings_commit = True sso_radius_host = flask.request.json['sso_radius_host'] or None if sso_radius_host != settings.app.sso_radius_host: changes.add('sso') settings.app.sso_radius_host = sso_radius_host if 'sso_org' in flask.request.json: settings_commit = True sso_org = flask.request.json['sso_org'] or None if sso_org: sso_org = utils.ObjectId(sso_org) else: sso_org = None if sso_org != settings.app.sso_org: changes.add('sso') if settings.app.sso and not sso_org: return utils.jsonify({ 'error': SSO_ORG_NULL, 'error_msg': SSO_ORG_NULL_MSG, }, 400) settings.app.sso_org = sso_org if 'sso_saml_url' in flask.request.json: settings_commit = True sso_saml_url = flask.request.json['sso_saml_url'] or None if sso_saml_url != settings.app.sso_saml_url: changes.add('sso') settings.app.sso_saml_url = sso_saml_url if 'sso_saml_issuer_url' in flask.request.json: settings_commit = True sso_saml_issuer_url = flask.request.json['sso_saml_issuer_url'] or None if sso_saml_issuer_url != settings.app.sso_saml_issuer_url: changes.add('sso') settings.app.sso_saml_issuer_url = sso_saml_issuer_url if 'sso_saml_cert' in flask.request.json: settings_commit = True sso_saml_cert = flask.request.json['sso_saml_cert'] or None if sso_saml_cert != settings.app.sso_saml_cert: changes.add('sso') settings.app.sso_saml_cert = sso_saml_cert if 'sso_okta_app_id' in flask.request.json: settings_commit = True sso_okta_app_id = flask.request.json['sso_okta_app_id'] or None if sso_okta_app_id != settings.app.sso_okta_app_id: changes.add('sso') settings.app.sso_okta_app_id = sso_okta_app_id if 'sso_okta_token' in flask.request.json: settings_commit = True sso_okta_token = flask.request.json['sso_okta_token'] or None if sso_okta_token != settings.app.sso_okta_token: changes.add('sso') settings.app.sso_okta_token = sso_okta_token if 'sso_okta_push' in flask.request.json: sso_mode = settings.app.sso if sso_mode and sso_mode in (SAML_OKTA_AUTH, SAML_OKTA_YUBICO_AUTH): settings_commit = True sso_okta_push = flask.request.json['sso_okta_push'] settings.app.sso_okta_push = True if sso_okta_push else False if 'sso_onelogin_app_id' in flask.request.json: settings_commit = True sso_onelogin_app_id = flask.request.json['sso_onelogin_app_id'] or \ None if sso_onelogin_app_id != settings.app.sso_onelogin_app_id: changes.add('sso') settings.app.sso_onelogin_app_id = sso_onelogin_app_id if 'sso_onelogin_id' in flask.request.json: settings_commit = True sso_onelogin_id = flask.request.json['sso_onelogin_id'] or None if sso_onelogin_id != settings.app.sso_onelogin_id: changes.add('sso') settings.app.sso_onelogin_id = sso_onelogin_id if 'sso_onelogin_secret' in flask.request.json: settings_commit = True sso_onelogin_secret = \ flask.request.json['sso_onelogin_secret'] or None if sso_onelogin_secret != settings.app.sso_onelogin_secret: changes.add('sso') settings.app.sso_onelogin_secret = sso_onelogin_secret if 'sso_onelogin_push' in flask.request.json: sso_mode = settings.app.sso if sso_mode and sso_mode in ( SAML_ONELOGIN_AUTH, SAML_ONELOGIN_YUBICO_AUTH): settings_commit = True sso_onelogin_push = flask.request.json['sso_onelogin_push'] settings.app.sso_onelogin_push = True if \ sso_onelogin_push else False if 'sso_cache' in flask.request.json: settings_commit = True sso_cache = True if \ flask.request.json['sso_cache'] else False if sso_cache != settings.app.sso_cache: changes.add('sso') settings.app.sso_cache = sso_cache if 'sso_client_cache' in flask.request.json: settings_commit = True sso_client_cache = True if \ flask.request.json['sso_client_cache'] else False if sso_client_cache != settings.app.sso_client_cache: changes.add('sso') settings.app.sso_client_cache = sso_client_cache if 'client_reconnect' in flask.request.json: settings_commit = True client_reconnect = True if \ flask.request.json['client_reconnect'] else False settings.user.reconnect = client_reconnect if 'sso_yubico_client' in flask.request.json: settings_commit = True sso_yubico_client = \ flask.request.json['sso_yubico_client'] or None if sso_yubico_client != settings.app.sso_yubico_client: changes.add('sso') settings.app.sso_yubico_client = sso_yubico_client if 'sso_yubico_secret' in flask.request.json: settings_commit = True sso_yubico_secret = \ flask.request.json['sso_yubico_secret'] or None if sso_yubico_secret != settings.app.sso_yubico_secret: changes.add('sso') settings.app.sso_yubico_secret = sso_yubico_secret if flask.request.json.get('theme'): settings_commit = True theme = 'light' if flask.request.json['theme'] == 'light' else 'dark' if theme != settings.app.theme: if theme == 'dark': event.Event(type=THEME_DARK) else: event.Event(type=THEME_LIGHT) settings.app.theme = theme if 'public_address' in flask.request.json: public_address = flask.request.json['public_address'] or None if public_address != settings.local.host.public_addr: settings.local.host.public_address = public_address settings.local.host.commit('public_address') if 'public_address6' in flask.request.json: public_address6 = flask.request.json['public_address6'] or None if public_address6 != settings.local.host.public_addr6: settings.local.host.public_address6 = public_address6 settings.local.host.commit('public_address6') if 'routed_subnet6' in flask.request.json: routed_subnet6 = flask.request.json['routed_subnet6'] if routed_subnet6: try: routed_subnet6 = ipaddress.IPv6Network( flask.request.json['routed_subnet6']) except (ipaddress.AddressValueError, ValueError): return utils.jsonify({ 'error': IPV6_SUBNET_INVALID, 'error_msg': IPV6_SUBNET_INVALID_MSG, }, 400) if routed_subnet6.prefixlen > 64: return utils.jsonify({ 'error': IPV6_SUBNET_SIZE_INVALID, 'error_msg': IPV6_SUBNET_SIZE_INVALID_MSG, }, 400) routed_subnet6 = str(routed_subnet6) else: routed_subnet6 = None if settings.local.host.routed_subnet6 != routed_subnet6: if server.get_online_ipv6_count(): return utils.jsonify({ 'error': IPV6_SUBNET_ONLINE, 'error_msg': IPV6_SUBNET_ONLINE_MSG, }, 400) settings.local.host.routed_subnet6 = routed_subnet6 settings.local.host.commit('routed_subnet6') if 'reverse_proxy' in flask.request.json: settings_commit = True reverse_proxy = flask.request.json['reverse_proxy'] settings.app.reverse_proxy = True if reverse_proxy else False if 'cloud_provider' in flask.request.json: settings_commit = True cloud_provider = flask.request.json['cloud_provider'] or None settings.app.cloud_provider = cloud_provider if 'route53_region' in flask.request.json: settings_commit = True settings.app.route53_region = utils.filter_str( flask.request.json['route53_region']) or None if 'route53_zone' in flask.request.json: settings_commit = True settings.app.route53_zone = utils.filter_str( flask.request.json['route53_zone']) or None for aws_key in ( 'us_east_1_access_key', 'us_east_1_secret_key', 'us_east_2_access_key', 'us_east_2_secret_key', 'us_west_1_access_key', 'us_west_1_secret_key', 'us_west_2_access_key', 'us_west_2_secret_key', 'us_gov_west_1_access_key', 'us_gov_west_1_secret_key', 'eu_west_1_access_key', 'eu_west_1_secret_key', 'eu_west_2_access_key', 'eu_west_2_secret_key', 'eu_central_1_access_key', 'eu_central_1_secret_key', 'ca_central_1_access_key', 'ca_central_1_secret_key', 'ap_northeast_1_access_key', 'ap_northeast_1_secret_key', 'ap_northeast_2_access_key', 'ap_northeast_2_secret_key', 'ap_southeast_1_access_key', 'ap_southeast_1_secret_key', 'ap_southeast_2_access_key', 'ap_southeast_2_secret_key', 'ap_south_1_access_key', 'ap_south_1_secret_key', 'sa_east_1_access_key', 'sa_east_1_secret_key', ): if settings.app.cloud_provider != 'aws': settings_commit = True setattr(settings.app, aws_key, None) elif aws_key in flask.request.json: settings_commit = True aws_value = flask.request.json[aws_key] if aws_value: setattr(settings.app, aws_key, utils.filter_str(aws_value)) else: setattr(settings.app, aws_key, None) if not settings.app.sso: settings.app.sso_match = None settings.app.sso_duo_token = None settings.app.sso_duo_secret = None settings.app.sso_duo_host = None settings.app.sso_org = None settings.app.sso_saml_url = None settings.app.sso_saml_issuer_url = None settings.app.sso_saml_cert = None settings.app.sso_okta_app_id = None settings.app.sso_okta_token = None settings.app.sso_onelogin_key = None settings.app.sso_onelogin_app_id = None settings.app.sso_onelogin_id = None settings.app.sso_onelogin_secret = None settings.app.sso_radius_secret = None settings.app.sso_radius_host = None else: if RADIUS_AUTH in settings.app.sso and \ settings.app.sso_duo_mode == 'passcode': return utils.jsonify({ 'error': RADIUS_DUO_PASSCODE, 'error_msg': RADIUS_DUO_PASSCODE_MSG, }, 400) if settings.app.sso == DUO_AUTH and \ settings.app.sso_duo_mode == 'passcode': return utils.jsonify({ 'error': DUO_PASSCODE, 'error_msg': DUO_PASSCODE_MSG, }, 400) for change in changes: flask.g.administrator.audit_event( 'admin_settings', _changes_audit_text[change], remote_addr=utils.get_remote_addr(), ) if settings_commit: settings.commit() admin.commit(admin.changed) if admin_event: event.Event(type=ADMINS_UPDATED) if org_event: for org in organization.iter_orgs(fields=('_id')): event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SETTINGS_UPDATED) if update_acme: try: acme.update_acme_cert() app.update_server(0.5) except: logger.exception('Failed to get LetsEncrypt cert', 'handler', acme_domain=settings.app.acme_domain, ) settings.app.acme_domain = None settings.app.acme_key = None settings.app.acme_timestamp = None settings.commit() return utils.jsonify({ 'error': ACME_ERROR, 'error_msg': ACME_ERROR_MSG, }, 400) elif update_cert: logger.info('Regenerating server certificate...', 'handler') utils.create_server_cert() app.update_server(0.5) elif update_server: app.update_server(0.5) response = flask.g.administrator.dict() response.update(_dict()) return utils.jsonify(response)
def settings_put(): admin = flask.g.administrator if 'username' in flask.request.json and flask.request.json['username']: admin.username = utils.filter_str( flask.request.json['username']).lower() if 'password' in flask.request.json and flask.request.json['password']: admin.password = flask.request.json['password'] if 'token' in flask.request.json and flask.request.json['token']: admin.generate_token() if 'secret' in flask.request.json and flask.request.json['secret']: admin.generate_secret() settings_commit = False if 'email_from' in flask.request.json: settings_commit = True email_from = flask.request.json['email_from'] settings.app.email_from = email_from or None if 'email_server' in flask.request.json: settings_commit = True email_server = flask.request.json['email_server'] settings.app.email_server = email_server or None if 'email_username' in flask.request.json: settings_commit = True email_username = flask.request.json['email_username'] settings.app.email_username = email_username or None if 'email_password' in flask.request.json: settings_commit = True email_password = flask.request.json['email_password'] settings.app.email_password = email_password or None if 'theme' in flask.request.json: settings_commit = True theme = 'dark' if flask.request.json['theme'] == 'dark' else 'light' if theme != settings.app.theme: if theme == 'dark': event.Event(type=THEME_DARK) else: event.Event(type=THEME_LIGHT) settings.app.theme = theme if 'public_address' in flask.request.json: public_address = flask.request.json['public_address'] settings.local.host.public_address = public_address settings.local.host.commit('public_address') if settings_commit: settings.commit() admin.commit(admin.changed) response = flask.g.administrator.dict() response.update({ 'theme': settings.app.theme, 'email_from': settings.app.email_from, 'email_server': settings.app.email_server, 'email_username': settings.app.email_username, 'email_password': bool(settings.app.email_password), 'public_address': settings.local.host.public_addr, }) return utils.jsonify(response)
def user_key_link_get(org_id, user_id): org = organization.get_by_id(org_id) return utils.jsonify(org.create_user_key_link(user_id))
def host_usage_get(hst, period): hst = host.get_by_id(hst) return utils.jsonify(hst.usage.get_period(period))
def subscription_delete(): if settings.app.demo_mode: return utils.demo_blocked() subscription.update_license(None) return utils.jsonify({})
def user_get(org_id, user_id=None, page=None): org = organization.get_by_id(org_id) if user_id: return utils.jsonify(org.get_user(user_id).dict()) page = flask.request.args.get('page', None) page = int(page) if page else page search = flask.request.args.get('search', None) limit = int(flask.request.args.get('limit', settings.user.page_count)) otp_auth = False server_count = 0 clients = collections.defaultdict(lambda: collections.defaultdict(list)) servers = [] for svr in org.iter_servers(fields=('name', 'otp_auth')): servers.append(svr) server_count += 1 if svr.otp_auth: otp_auth = True users = [] users_server_data = collections.defaultdict(dict) fields = ( 'organization', 'organization_name', 'name', 'email', 'type', 'otp_secret', 'disabled', ) for user in org.iter_users(page=page, search=search, search_limit=limit, fields=fields): user_id = user.id is_client = user_id in clients user_dict = user.dict() user_dict['status'] = is_client user_dict['otp_auth'] = otp_auth server_data = [] for svr in servers: server_id = svr.id if clients[user_id][server_id]: for device in clients[user_id][server_id]: device['id'] = device.pop('device_id', server_id) device['name'] = svr.name device['status'] = True device['virt_address'] = device['virt_address'].split( '/')[0] server_data.append(device) else: data = { 'id': server_id, 'name': svr.name, 'status': False, 'type': None, 'client_id': None, 'device_name': None, 'platform': None, 'real_address': None, 'virt_address': None, 'connected_since': None } server_data.append(data) users_server_data[user_id][server_id] = data user_dict['servers'] = sorted(server_data, key=lambda x: x['name']) users.append(user_dict) ip_addrs_iter = server.multi_get_ip_addr(org_id, users_server_data.keys()) for user_id, server_id, ip_add in ip_addrs_iter: user_server_data = users_server_data[user_id].get(server_id) if user_server_data: if not user_server_data['virt_address']: user_server_data['virt_address'] = ip_add if page is not None: return utils.jsonify({ 'page': page, 'page_total': org.page_total, 'server_count': server_count, 'users': users, }) elif search is not None: return utils.jsonify({ 'search': search, 'search_more': limit < org.last_search_count, 'search_limit': limit, 'search_count': org.last_search_count, 'search_time': round((time.time() - flask.g.start), 4), 'server_count': server_count, 'users': users, }) else: return utils.jsonify(users)
def sso_yubico_post(): sso_mode = settings.app.sso token = utils.filter_str(flask.request.json.get('token')) or None key = utils.filter_str(flask.request.json.get('key')) or None if sso_mode not in (GOOGLE_YUBICO_AUTH, SLACK_YUBICO_AUTH, SAML_YUBICO_AUTH, SAML_OKTA_YUBICO_AUTH, SAML_ONELOGIN_YUBICO_AUTH): return flask.abort(404) if not token or not key: return utils.jsonify( { 'error': TOKEN_INVALID, 'error_msg': TOKEN_INVALID_MSG, }, 401) tokens_collection = mongo.get_collection('sso_tokens') doc = tokens_collection.find_one({ '_id': token, }) if not doc or doc['_id'] != token or doc['type'] != YUBICO_AUTH: return utils.jsonify( { 'error': TOKEN_INVALID, 'error_msg': TOKEN_INVALID_MSG, }, 401) username = doc['username'] email = doc['email'] org_id = doc['org_id'] groups = set(doc['groups'] or []) valid, yubico_id = sso.auth_yubico(key) if not valid: return utils.jsonify( { 'error': YUBIKEY_INVALID, 'error_msg': YUBIKEY_INVALID_MSG, }, 401) usr = user.find_user_auth(name=username, auth_type=sso_mode) if not usr: org = organization.get_by_id(org_id) if not org: return flask.abort(405) usr = org.find_user(name=username) else: org = usr.org if not usr: usr = org.new_user(name=username, email=email, type=CERT_CLIENT, auth_type=sso_mode, yubico_id=yubico_id, groups=list(groups) if groups else None) usr.audit_event('user_created', 'User created with single sign-on', remote_addr=utils.get_remote_addr()) event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) else: if yubico_id != usr.yubico_id: return utils.jsonify( { 'error': YUBIKEY_INVALID, 'error_msg': YUBIKEY_INVALID_MSG, }, 401) if usr.disabled: return flask.abort(403) if groups and groups - set(usr.groups or []): usr.groups = list(set(usr.groups or []) | groups) usr.commit('groups') if usr.auth_type != sso_mode: usr.auth_type = sso_mode usr.commit('auth_type') key_link = org.create_user_key_link(usr.id, one_time=True) usr.audit_event( 'user_profile', 'User profile viewed from single sign-on', remote_addr=utils.get_remote_addr(), ) return utils.jsonify( { 'redirect': utils.get_url_root() + key_link['view_url'], }, 200)
def host_usage_get(host_id, period): hst = host.get_host(id=host_id) return utils.jsonify(hst.usage.get_period(period))
def password_post(): password = flask.request.json['password'][:512] app_server.set_password(password) return utils.jsonify({})