def __new__(cls, id=None, doc=None, spec=None, fields=None, upsert=False, **kwargs): from pritunl import utils fields = fields or cls.fields mongo_object = object.__new__(cls) mongo_object.changed = set() mongo_object.unseted = set() mongo_object.id = id mongo_object.loaded_fields = fields if id or doc or spec: mongo_object.exists = True try: mongo_object.load(doc=doc, spec=spec, fields=fields) except NotFound: if not upsert: return None mongo_object.exists = False if not id: mongo_object.id = utils.ObjectId() else: mongo_object.exists = False mongo_object.id = utils.ObjectId() return mongo_object
def connected(self, client): client_id = client['client_id'] user_id = utils.ObjectId(client['user_id']) org_id = utils.ObjectId(client['org_id']) device = self.devices[user_id].get(client_id) if not device: self.instance_com.push_output( 'ERROR Unknown client connected org_id=%s user_id=%s' % ( org_id, user_id)) return domain = device['user'] + '.' + device['org'] timestamp = utils.now() domain_hash = hashlib.md5() domain_hash.update(domain) domain_hash = bson.binary.Binary(domain_hash.digest(), subtype=bson.binary.MD5_SUBTYPE) try: id = self.collection.insert({ 'user_id': user_id, 'server_id': self.server.id, 'domain': domain_hash, 'timestamp': timestamp, 'platform': device['platform'], 'type': device['type'], 'device_name': device['device_name'], 'mac_addr': device['mac_addr'], 'network': self.server.network, 'real_address': device['real_address'], 'virt_address': device['virt_address'], 'connected_since': int(timestamp.strftime('%s')), }) except: logger.exception('Error adding client', 'server', server_id=self.server.id, ) self.instance_com.client_kill(device) return device['id'] = id self.clients.append({ 'id': id, 'client_id': client_id, 'user_id': user_id, 'org_id': org_id, 'virt_address': device['virt_address'], 'timestamp': timestamp, }) self.instance_com.push_output('User connected org_id=%s user_id=%s' % ( org_id, user_id)) self.send_event()
def publish(channels, message, extra=None, transaction=None): if cache.has_cache: return cache.publish(channels, message, extra=extra) collection = mongo.get_collection('messages') doc = { 'message': message, 'timestamp': utils.now(), } if extra: for key, val in list(extra.items()): doc[key] = val # ObjectId must be set by server and ObjectId order must match $natural # order. Docs sent in order on client are not guaranteed to match $natural # order on server. Nonce is added to force an insert from upsert where # insert is not supported. # When using inserts manipulate=False must be set to prevent pymongo # from setting ObjectId locally. if transaction: tran_collection = transaction.collection(collection.name_str) if isinstance(channels, str): doc['channel'] = channels tran_collection.update({ 'nonce': utils.ObjectId(), }, { '$set': doc, }, upsert=True) else: for channel in channels: doc_copy = doc.copy() doc_copy['channel'] = channel tran_collection.bulk().find({ 'nonce': utils.ObjectId(), }).upsert().update({ '$set': doc_copy, }) tran_collection.bulk_execute() else: if isinstance(channels, str): doc['channel'] = channels collection.insert(doc, manipulate=False) else: docs = [] for channel in channels: doc_copy = doc.copy() doc_copy['channel'] = channel docs.append(doc_copy) collection.insert(docs, manipulate=False)
def _upgrade_org(org_id, org_path): organizations_db = get_collection('organizations') org_conf_path = os.path.join(org_path, 'ca.conf') spec = { '_id': utils.ObjectId(org_id), } update_doc = { 'name': None, 'type': ORG_DEFAULT, 'ca_certificate': None, 'ca_private_key': None, } with open(org_conf_path, 'r') as conf_file: for line in conf_file.readlines(): line = line.strip() name, value = line.split('=', 1) if name == 'name': update_doc['name'] = value elif name == 'pool' and value == 'true': update_doc['type'] = ORG_POOL org_ca_cert_path = os.path.join(org_path, 'certs', 'ca.crt') with open(org_ca_cert_path, 'r') as org_cert_file: update_doc['ca_certificate'] = org_cert_file.read().rstrip('\n') org_ca_key_path = os.path.join(org_path, 'keys', 'ca.key') with open(org_ca_key_path, 'r') as org_key_file: update_doc['ca_private_key'] = org_key_file.read().rstrip('\n') organizations_db.update(spec, update_doc, upsert=True)
def link_location_exclude_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 or lnk.type == DIRECT: return flask.abort(404) loc = lnk.get_location(location_id) if not loc: return flask.abort(404) exclude_id = utils.ObjectId(flask.request.json.get('exclude_id')) loc.add_exclude(exclude_id) lnk.commit('excludes') event.Event(type=LINKS_UPDATED) return utils.jsonify({ 'location_id': exclude_id, })
def parse_object_id(_, values): if values: for key in values: if key.endswith('_id'): val = values[key] if len(val) > 10: values[key] = utils.ObjectId(val)
def event_get(cursor=None): if check_global_interrupt(): raise flask.abort(500) if cursor is not None: cursor = utils.ObjectId(cursor) return utils.jsonify(event.get_events(cursor=cursor))
def link_state_delete(): if settings.app.demo_mode: return utils.demo_blocked() auth_token = flask.request.headers.get('Auth-Token', None) auth_timestamp = flask.request.headers.get('Auth-Timestamp', None) auth_nonce = flask.request.headers.get('Auth-Nonce', None) auth_signature = flask.request.headers.get('Auth-Signature', None) if not auth_token or not auth_timestamp or not auth_nonce or \ not auth_signature: return flask.abort(406) auth_token = auth_token[:256] auth_timestamp = auth_timestamp[:64] auth_nonce = auth_nonce[:32] auth_signature = auth_signature[:512] try: if abs(int(auth_timestamp) - int(utils.time_now())) > \ settings.app.auth_time_window: return flask.abort(408) except ValueError: return flask.abort(405) host = link.get_host(utils.ObjectId(auth_token)) if not host: return flask.abort(404) auth_string = '&'.join([ auth_token, auth_timestamp, auth_nonce, flask.request.method, flask.request.path, ]) if len(auth_string) > AUTH_SIG_STRING_MAX_LEN: return flask.abort(413) auth_test_signature = base64.b64encode( hmac.new(host.secret.encode(), auth_string.encode(), hashlib.sha512).digest()).decode() if not utils.const_compare(auth_signature, auth_test_signature): return flask.abort(401) nonces_collection = mongo.get_collection('auth_nonces') try: nonces_collection.insert({ 'token': auth_token, 'nonce': auth_nonce, 'timestamp': utils.now(), }) except pymongo.errors.DuplicateKeyError: return flask.abort(409) host.set_inactive() return utils.jsonify({})
def auth_delete(): admin_id = flask.session.get('admin_id') session_id = flask.session.get('session_id') if admin_id and session_id: admin_id = utils.ObjectId(admin_id) auth.clear_session(admin_id, session_id) flask.session.clear() return utils.jsonify({ 'authenticated': False, })
def disconnected(self, client): client_id = client.get('client_id') user_id = client.get('user_id') user_id = utils.ObjectId(user_id) if user_id else None org_id = client.get('org_id') org_id = utils.ObjectId(org_id) if org_id else None devices = self.devices[user_id] device = devices.get(client_id) devices.pop(client_id, None) if device: virt_address = device['virt_address'] if self.ips.get(virt_address) == client_id: self.ips.pop(virt_address, None) if virt_address in self.dyn_ips: try: self.dyn_ips.remove(virt_address) except KeyError: pass self.ip_pool.append(virt_address.split('/')[0]) id = device.get('id') if id: try: self.collection.remove({ '_id': id, }) except: logger.exception( 'Error removing client', 'server', server_id=self.server.id, ) self.instance_com.push_output( 'User disconnected org_id=%s user_id=%s' % (org_id, user_id)) self.send_event()
def __init__(self, priority=None, retry=None, **kwargs): mongo.MongoObject.__init__(self, **kwargs) self.type = self.type self.reserve_id = self.reserve_id self.runner_id = utils.ObjectId() self.claimed = False self.queue_com = QueueCom() self.keep_alive_thread = None if priority is not None: self.priority = priority if retry is not None: self.retry = retry
def client_connected(self, client): client_id = client['client_id'] org_id = utils.ObjectId(client['org_id']) user_id = utils.ObjectId(client['user_id']) devices = self.client_devices[user_id] data = None for device in devices: if device['client_id'] == client_id: data = device break if not data: self.push_output( 'ERROR Unknown client connected org_id=%s user_id=%s' % (org_id, user_id)) return self.clients.append({ 'id': user_id, 'client_id': client_id, 'device_id': data['device_id'], 'device_name': data['device_name'], 'platform': data['platform'], 'type': data['type'], 'real_address': data['real_address'], 'virt_address': data['virt_address'], 'connected_since': int(utils.now().strftime('%s')), }) if data['type'] == CERT_CLIENT: self.clients_active += 1 self.update_clients() self.push_output('User connected org_id=%s user_id=%s' % (org_id, user_id))
def event_get(cursor=None): if settings.app.demo_mode: time.sleep(0.1) return utils.jsonify([{ 'id': 'demo', }]) if check_global_interrupt(): raise flask.abort(500) if cursor is not None: cursor = utils.ObjectId(cursor) return utils.jsonify(event.get_events(cursor=cursor, yield_app_server=True))
def __init__(self, server): self.server = server self.id = utils.ObjectId() self.resource_lock = None self.interrupt = False self.sock_interrupt = False self.clean_exit = False self.interface = None self.primary_user = None self.process = None self.auth_log_process = None self.iptables_rules = [] self.server_links = [] self._temp_path = utils.get_temp_path() self.ovpn_conf_path = os.path.join(self._temp_path, OVPN_CONF_NAME) self.management_socket_path = os.path.join( settings.conf.var_run_path, MANAGEMENT_SOCKET_NAME % self.id)
def auth_delete(): admin_id = utils.session_opt_str('admin_id') session_id = utils.session_opt_str('session_id') remote_addr = utils.get_remote_addr() journal.entry( journal.ADMIN_SESSION_END, admin_id=admin_id, session_id=session_id, remote_address=remote_addr, ) if admin_id and session_id: admin_id = utils.ObjectId(admin_id) auth.clear_session(admin_id, str(session_id)) flask.session.clear() return utils.jsonify({ 'authenticated': False, })
def __init__(self, lock_id=None, priority=None, ttl=None, **kwargs): mongo.MongoObject.__init__(self, **kwargs) if lock_id is not None: self.lock_id = lock_id if self.lock_id is None: self.lock_id = utils.ObjectId() if priority is not None: self.priority = priority if ttl is not None: self.ttl = ttl if self.actions: actions_json = zlib.decompress(self.actions) self.action_sets = json.loads( actions_json, object_hook=utils.json_object_hook_handler) else: self.action_sets = []
def __init__(self, server): self.server = server self.id = utils.ObjectId() self.interrupt = False self.sock_interrupt = False self.clean_exit = False self.interface = None self.bridge_interface = None self.primary_user = None self.process = None self.vxlan = None self.iptables = iptables.Iptables() self.iptables_lock = threading.Lock() self.tun_nat = False self.server_links = [] self.route_advertisements = set() self._temp_path = utils.get_temp_path() self.ovpn_conf_path = os.path.join(self._temp_path, OVPN_CONF_NAME) self.management_socket_path = os.path.join( settings.conf.var_run_path, MANAGEMENT_SOCKET_NAME % self.id, )
def publish(channels, message, extra=None, cap=50, ttl=300): if isinstance(channels, str): channels = [channels] for channel in channels: doc = { '_id': utils.ObjectId(), 'message': message, 'timestamp': utils.now(), } if extra: for key, val in extra.items(): doc[key] = val doc = json.dumps(doc, default=utils.json_default) pipe = _client.pipeline() pipe.lpush(channel, doc) pipe.ltrim(channel, 0, cap) if ttl: pipe.expire(channel, ttl) pipe.publish(channel, doc) pipe.execute()
def client_disconnect(self, client): client_id = client.get('client_id') user_id = client.get('user_id') user_id = utils.ObjectId(user_id) if user_id else None user_type = None virt_address = None devices = self.client_devices[user_id] for i, device in enumerate(devices): if device['client_id'] == client_id: virt_address = device['virt_address'] del devices[i] break for i, clt in enumerate(self.clients): if clt['client_id'] == client_id: user_type = clt['type'] virt_address = clt['virt_address'] del self.clients[i] break if virt_address: if virt_address in self.client_ips: self.client_ips.remove(virt_address) if virt_address in self.client_dyn_ips: self.client_dyn_ips.remove(virt_address) self.ip_pool.append(virt_address.split('/')[0]) if user_type == CERT_CLIENT: self.clients_active -= 1 self.update_clients() self.push_output('User disconnected org_id=%s user_id=%s' % (client.get('org_id'), user_id))
def __init__(self, run_id=None, **kwargs): mongo.MongoObject.__init__(self) self.type = self.type self.runner_id = utils.ObjectId()
def thread(): platforms = list(DESKTOP_PLATFORMS) start_timestamp = datetime.datetime(2015, 12, 28, 4, 1, 0) hosts_collection = mongo.get_collection('hosts') servers_collection = mongo.get_collection('servers') clients_collection = mongo.get_collection('clients') clients_collection.remove({}) for hst in host.iter_hosts(): hosts_collection.update({ '_id': hst.id, }, { '$set': { 'server_count': 0, 'device_count': 0, 'cpu_usage': 0, 'mem_usage': 0, 'thread_count': 0, 'open_file_count': 0, 'status': ONLINE, 'start_timestamp': start_timestamp, 'ping_timestamp': start_timestamp, 'auto_public_address': None, 'auto_public_address6': None, 'auto_public_host': hst.name + '.pritunl.com', 'auto_public_host6': hst.name + '.pritunl.com', } }) for svr in server.iter_servers(): prefered_hosts = host.get_prefered_hosts(svr.hosts, svr.replica_count) instances = [] for hst in prefered_hosts: instances.append({ 'instance_id': utils.ObjectId(), 'host_id': hst, 'ping_timestamp': utils.now(), }) servers_collection.update({ '_id': svr.id, }, { '$set': { 'status': ONLINE, 'pool_cursor': None, 'start_timestamp': start_timestamp, 'availability_group': DEFAULT, 'instances': instances, 'instances_count': len(instances), } }) for org in svr.iter_orgs(): for usr in org.iter_users(): if usr.type != CERT_CLIENT: continue virt_address = svr.get_ip_addr(org.id, usr.id) virt_address6 = svr.ip4to6(virt_address) doc = { '_id': utils.ObjectId(), 'user_id': usr.id, 'server_id': svr.id, 'host_id': settings.local.host_id, 'timestamp': start_timestamp, 'platform': random.choice(platforms), 'type': CERT_CLIENT, 'device_name': utils.random_name(), 'mac_addr': utils.rand_str(16), 'network': svr.network, 'real_address': str( ipaddress.IPAddress( 100000000 + random.randint(0, 1000000000))), 'virt_address': virt_address, 'virt_address6': virt_address6, 'host_address': settings.local.host.local_addr, 'host_address6': settings.local.host.local_addr6, 'dns_servers': [], 'dns_suffix': None, 'connected_since': int(start_timestamp.strftime('%s')), } clients_collection.insert(doc) for lnk in link.iter_links(): lnk.status = ONLINE lnk.commit() for location in lnk.iter_locations(): active = False for hst in location.iter_hosts(): if not active: hst.active = True active = True hst.status = AVAILABLE hst.commit(('active', 'status')) logger.info('Demo initiated', 'demo')
def parse_line(self, line): if self.client: if line == '>CLIENT:ENV,END': cmd = self.client['cmd'] if cmd == 'connect': self.clients.connect(self.client) elif cmd == 'reauth': self.clients.connect(self.client, reauth=True) elif cmd == 'connected': self.clients.connected(self.client.get('client_id')) elif cmd == 'disconnected': self.clients.disconnected(self.client.get('client_id')) self.client = None elif line.startswith('>CLIENT:ENV'): env_key, env_val = line[12:].split('=', 1) if env_key == 'tls_id_0': tls_env = ''.join(x for x in env_val if x in VALID_CHARS) o_index = tls_env.find('O=') cn_index = tls_env.find('CN=') if o_index < 0 or cn_index < 0: self.send_client_deny( self.client, 'Failed to parse org_id and user_id') self.client = None return if o_index > cn_index: org_id = tls_env[o_index + 2:] user_id = tls_env[3:o_index] else: org_id = tls_env[2:cn_index] user_id = tls_env[cn_index + 3:] self.client['org_id'] = utils.ObjectId(org_id) self.client['user_id'] = utils.ObjectId(user_id) elif env_key == 'IV_HWADDR': self.client['mac_addr'] = env_val elif env_key == 'untrusted_ip': self.client['remote_ip'] = env_val elif env_key == 'untrusted_ip6': remote_ip = env_val if remote_ip.startswith('::ffff:'): remote_ip = remote_ip.split(':')[-1] self.client['remote_ip'] = remote_ip elif env_key == 'IV_PLAT' and not self.client.get('platform'): if 'chrome' in env_val.lower(): env_val = 'chrome' self.client['device_id'] = uuid.uuid4().hex self.client['device_name'] = 'chrome-os' self.client['platform'] = env_val elif env_key == 'UV_ID': self.client['device_id'] = env_val elif env_key == 'UV_NAME': self.client['device_name'] = env_val elif env_key == 'UV_PLATFORM': self.client['platform'] = env_val elif env_key == 'password': self.client['password'] = env_val else: self.push_output('CCOM> %s' % line[1:]) elif line.startswith('>BYTECOUNT_CLI'): client_id, bytes_recv, bytes_sent = line.split(',') client_id = client_id.split(':')[1] self.parse_bytecount(client_id, int(bytes_recv), int(bytes_sent)) elif line.startswith('>CLIENT:CONNECT'): _, client_id, key_id = line.split(',') self.client = { 'cmd': 'connect', 'client_id': client_id, 'key_id': key_id, } elif line.startswith('>CLIENT:REAUTH'): _, client_id, key_id = line.split(',') self.client = { 'cmd': 'reauth', 'client_id': client_id, 'key_id': key_id, } elif line.startswith('>CLIENT:ESTABLISHED'): _, client_id = line.split(',') self.client = { 'cmd': 'connected', 'client_id': client_id, } elif line.startswith('>CLIENT:DISCONNECT'): _, client_id = line.split(',') self.client = { 'cmd': 'disconnected', 'client_id': client_id, } elif line.startswith('SUCCESS:'): self.push_output('COM> %s' % line)
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_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_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_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_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 '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', 'eu_west_1_access_key', 'eu_west_1_secret_key', 'eu_central_1_access_key', 'eu_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 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_host = None settings.app.sso_token = None settings.app.sso_secret = None 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_yubico_client = None settings.app.sso_yubico_secret = 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_token = None settings.app.sso_onelogin_key = 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 link_state_put(): if settings.app.demo_mode: return utils.demo_blocked() auth_token = flask.request.headers.get('Auth-Token', None) auth_timestamp = flask.request.headers.get('Auth-Timestamp', None) auth_nonce = flask.request.headers.get('Auth-Nonce', None) auth_signature = flask.request.headers.get('Auth-Signature', None) if not auth_token or not auth_timestamp or not auth_nonce or \ not auth_signature: return flask.abort(406) auth_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) host = link.get_host(utils.ObjectId(auth_token)) if not host: return flask.abort(404) auth_string = '&'.join([ auth_token, auth_timestamp, auth_nonce, flask.request.method, flask.request.path, ]) if len(auth_string) > AUTH_SIG_STRING_MAX_LEN: return flask.abort(413) auth_test_signature = base64.b64encode( hmac.new(host.secret.encode(), auth_string, 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) host.load_link() host.version = flask.request.json.get('version') host.public_address = flask.request.json.get('public_address') host.local_address = flask.request.json.get('local_address') host.address6 = flask.request.json.get('address6') data = json.dumps(host.get_state(), default=lambda x: str(x)) data += (16 - len(data) % 16) * '\x00' iv = os.urandom(16) key = hashlib.sha256(host.secret).digest() cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()).encryptor() enc_data = base64.b64encode(cipher.update(data) + cipher.finalize()) enc_signature = base64.b64encode( hmac.new(host.secret.encode(), enc_data, hashlib.sha512).digest()) resp = flask.Response(response=enc_data, mimetype='application/base64') resp.headers.add('Cache-Control', 'no-cache, no-store, must-revalidate') resp.headers.add('Pragma', 'no-cache') resp.headers.add('Expires', 0) resp.headers.add('Cipher-IV', base64.b64encode(iv)) resp.headers.add('Cipher-Signature', enc_signature) return resp
def iter_users(self, page=None, search=None, search_limit=None, fields=None, include_pool=False): spec = { 'org_id': self.id, 'type': CERT_CLIENT, } searched = False type_search = False limit = None skip = None page_count = settings.user.page_count if fields: fields = {key: True for key in fields} if search is not None: searched = True n = search.find('id:') if n != -1: user_id = search[n + 3:].split(None, 1) user_id = user_id[0] if user_id else '' if user_id: type_search = True spec['_id'] = utils.ObjectId(user_id) search = search[:n] + search[n + 3 + len(user_id):].strip() n = search.find('type:') if n != -1: user_type = search[n + 5:].split(None, 1) user_type = user_type[0] if user_type else '' if user_type: type_search = True spec['type'] = user_type search = search[:n] + search[n + 5 + len(user_type):].strip() n = search.find('group:') if n != -1: user_group = search[n + 6:].split(None, 1) user_group = user_group[0] if user_group else '' if user_group: spec['groups'] = user_group search = search[:n] + search[n + 6 + len(user_group):].strip() n = search.find('email:') if n != -1: email = search[n + 6:].split(None, 1) email = email[0] if email else '' if email: spec['email'] = { '$regex': '.*%s.*' % email, '$options': 'i', } search = search[:n] + search[n + 6 + len(email):].strip() n = search.find('status:') if n != -1: status = search[n + 7:].split(None, 1) status = status[0] if status else '' search = search[:n] + search[n + 7 + len(status):].strip() if status not in (ONLINE, OFFLINE): return user_ids = self.clients_collection.find( None, { '_id': True, 'user_id': True, }).distinct('user_id') if status == ONLINE: spec['_id'] = {'$in': user_ids} else: spec['_id'] = {'$nin': user_ids} spec['name'] = { '$regex': '.*%s.*' % search.strip(), '$options': 'i', } limit = search_limit or page_count elif page is not None: limit = page_count skip = page * page_count if page else 0 cursor = user.User.collection.find(spec, fields).sort( 'name', pymongo.ASCENDING) if skip is not None: cursor = cursor.skip(page * page_count if page else 0) if limit is not None: cursor = cursor.limit(limit + 1) if searched: self.last_search_count = cursor.count() if limit is None: for doc in cursor: yield user.User(self, doc=doc, fields=fields) else: count = 0 for doc in cursor: count += 1 if count > limit: return yield user.User(self, doc=doc, fields=fields) if type_search: return if include_pool: spec['type'] = { '$in': [CERT_SERVER, CERT_CLIENT_POOL, CERT_SERVER_POOL] } else: spec['type'] = CERT_SERVER cursor = user.User.collection.find(spec, fields).sort( 'name', pymongo.ASCENDING) for doc in cursor: yield user.User(self, doc=doc, fields=fields)
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_token' in flask.request.json: sso_token = flask.request.json['sso_token'] settings_commit = True settings.app.sso_token = sso_token or None if 'sso_secret' in flask.request.json: sso_secret = flask.request.json['sso_secret'] settings_commit = True settings.app.sso_secret = sso_secret or None if 'sso_host' in flask.request.json: sso_host = flask.request.json['sso_host'] settings_commit = True settings.app.sso_host = sso_host or None if 'sso_admin' in flask.request.json: sso_admin = flask.request.json['sso_admin'] settings_commit = True settings.app.sso_admin = sso_admin 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 'public_address6' in flask.request.json: public_address6 = flask.request.json['public_address6'] 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 '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 not settings.app.sso: settings.app.sso_match = None settings.app.sso_token = None settings.app.sso_secret = None settings.app.sso_host = None settings.app.sso_admin = None settings.app.sso_org = 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': settings.app.sso, 'sso_match': settings.app.sso_match, 'sso_token': settings.app.sso_token, 'sso_secret': settings.app.sso_secret, 'sso_host': settings.app.sso_host, 'sso_admin': settings.app.sso_admin, 'sso_org': settings.app.sso_org, 'public_address': settings.local.host.public_addr, }) return utils.jsonify(response)
def settings_put(): if settings.app.demo_mode: return utils.demo_blocked() org_event = False admin = flask.g.administrator changes = set() 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 'token' in flask.request.json and flask.request.json['token']: admin.generate_token() changes.add('token') if 'secret' in flask.request.json and flask.request.json['secret']: admin.generate_secret() changes.add('token') settings_commit = False if 'auditing' in flask.request.json: settings_commit = True auditing = flask.request.json['auditing'] or None if settings.app.auditing != auditing: 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 'datadog_api_key' in flask.request.json: settings_commit = True datadog_api_key = flask.request.json['datadog_api_key'] or None settings.app.datadog_api_key = datadog_api_key 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_token' in flask.request.json: settings_commit = True sso_token = flask.request.json['sso_token'] or None if sso_token != settings.app.sso_token: changes.add('sso') settings.app.sso_token = sso_token if 'sso_secret' in flask.request.json: settings_commit = True sso_secret = flask.request.json['sso_secret'] or None if sso_secret != settings.app.sso_secret: changes.add('sso') settings.app.sso_secret = sso_secret if 'sso_host' in flask.request.json: settings_commit = True sso_host = flask.request.json['sso_host'] or None if sso_host != settings.app.sso_host: changes.add('sso') settings.app.sso_host = sso_host if 'sso_admin' in flask.request.json: settings_commit = True sso_admin = flask.request.json['sso_admin'] or None if sso_admin != settings.app.sso_admin: changes.add('sso') settings.app.sso_admin = sso_admin if 'sso_org' in flask.request.json: settings_commit = True sso_org = flask.request.json['sso_org'] if sso_org: sso_org = utils.ObjectId(sso_org) else: sso_org = None if sso_org != settings.app.sso_org: changes.add('sso') 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_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_onelogin_key' in flask.request.json: settings_commit = True sso_onelogin_key = flask.request.json['sso_onelogin_key'] or None if sso_onelogin_key != settings.app.sso_onelogin_key: changes.add('sso') settings.app.sso_onelogin_key = sso_onelogin_key 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 'public_address6' in flask.request.json: public_address6 = flask.request.json['public_address6'] 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 '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 not settings.app.sso: settings.app.sso_match = None settings.app.sso_token = None settings.app.sso_secret = None settings.app.sso_host = None settings.app.sso_admin = 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_token = None settings.app.sso_onelogin_key = None for change in changes: auth.audit_event( 'admin_settings', _changes_audit_text[change], remote_addr=utils.get_remote_addr(), ) if settings_commit: settings.commit() admin.commit(admin.changed) 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) response = flask.g.administrator.dict() response.update({ 'theme': settings.app.theme, 'auditing': settings.app.auditing, 'monitoring': settings.app.monitoring, 'datadog_api_key': settings.app.datadog_api_key, '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), 'pin_mode': settings.user.pin_mode, 'sso': settings.app.sso, 'sso_match': settings.app.sso_match, 'sso_token': settings.app.sso_token, 'sso_secret': settings.app.sso_secret, 'sso_host': settings.app.sso_host, 'sso_admin': settings.app.sso_admin, 'sso_org': settings.app.sso_org, 'sso_saml_url': settings.app.sso_saml_url, 'sso_saml_issuer_url': settings.app.sso_saml_issuer_url, 'sso_saml_cert': settings.app.sso_saml_cert, 'sso_okta_token': settings.app.sso_okta_token, 'sso_onelogin_key': settings.app.sso_onelogin_key, 'public_address': settings.local.host.public_addr, }) return utils.jsonify(response)
def check_session(): auth_token = flask.request.headers.get('Auth-Token', None) if auth_token: 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 False auth_nonce = auth_nonce[:32] try: if abs(int(auth_timestamp) - int(utils.time_now())) > \ settings.app.auth_time_window: return False except ValueError: return False administrator = find_user(token=auth_token) if not administrator: return False 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 False auth_test_signature = base64.b64encode( hmac.new(administrator.secret.encode(), auth_string, hashlib.sha256).digest()) if auth_signature != auth_test_signature: return False try: Administrator.nonces_collection.insert( { 'token': auth_token, 'nonce': auth_nonce, 'timestamp': utils.now(), }, w=0) except pymongo.errors.DuplicateKeyError: return False else: if not flask.session: return False admin_id = flask.session.get('admin_id') if not admin_id: return False admin_id = utils.ObjectId(admin_id) session_id = flask.session.get('session_id') administrator = get_user(admin_id, session_id) if not administrator: return False if not settings.conf.ssl and flask.session.get( 'source') != utils.get_remote_addr(): flask.session.clear() return False session_timeout = settings.app.session_timeout if session_timeout and int(utils.time_now()) - \ flask.session['timestamp'] > session_timeout: flask.session.clear() return False flask.session['timestamp'] = int(utils.time_now()) flask.g.administrator = administrator return True
def connect(self, client): try: client_id = client['client_id'] org_id = utils.ObjectId(client['org_id']) user_id = utils.ObjectId(client['user_id']) device_id = client.get('device_id') device_name = client.get('device_name') platform = client.get('platform') mac_addr = client.get('mac_addr') otp_code = client.get('otp_code') remote_ip = client.get('remote_ip') devices = self.devices[user_id] if not _limiter.validate(remote_ip): self.instance_com.send_client_deny( client, 'Too many connect requests') return org = self.server.get_org(org_id, fields=['_id', 'name']) if not org: self.instance_com.send_client_deny( client, 'Organization is not valid') return user = org.get_user(user_id, fields=('_id', 'name', 'email', 'type', 'auth_type', 'disabled', 'otp_secret', 'link_server_id')) if not user: self.instance_com.send_client_deny(client, 'User is not valid') return if user.disabled: logger.LogEntry(message='User failed authentication, ' + 'disabled user "%s".' % (user.name)) self.instance_com.send_client_deny(client, 'User is disabled') return if not user.auth_check(): logger.LogEntry(message='User failed authentication, ' + 'Google authentication failed "%s".' % (user.name)) self.instance_com.send_client_deny( client, 'User failed authentication') return if self.server.otp_auth and user.type == CERT_CLIENT and \ not user.verify_otp_code(otp_code, remote_ip): logger.LogEntry(message='User failed two-step ' + 'authentication "%s".' % user.name) self.instance_com.send_client_deny(client, 'Invalid OTP code') return client_conf = self.generate_client_conf(user) if not self.server.multi_device: virt_address = self.server.get_ip_addr(org.id, user_id) if virt_address and virt_address in self.ips: for cid, device in devices.items(): if device['virt_address'] == virt_address: self.instance_com.client_kill(device) else: virt_address = None if devices and device_id: for cid, device in devices.items(): if device['device_id'] == device_id: self.instance_com.client_kill(device) if not virt_address: virt_address = self.server.get_ip_addr(org.id, user_id) if virt_address and virt_address in self.ips: virt_address = None if not virt_address: while True: try: ip_addr = self.ip_pool.pop() except IndexError: break ip_addr = '%s/%s' % ( ip_addr, self.ip_network.prefixlen) if ip_addr not in self.ips: virt_address = ip_addr self.dyn_ips.add(virt_address) break if virt_address: self.ips[virt_address] = client_id devices[client_id] = { 'user': user.name, 'user_id': user_id, 'org': org.name, 'org_id': org_id, 'client_id': client_id, 'device_id': device_id, 'device_name': device_name, 'type': user.type, 'platform': platform, 'mac_addr': mac_addr, 'virt_address': virt_address, 'real_address': remote_ip, } client_conf += 'ifconfig-push %s %s\n' % utils.parse_network( virt_address) if self.server.debug: self.instance_com.push_output('Client conf %s:' % user_id) for conf_line in client_conf.split('\n'): if conf_line: self.instance_com.push_output(' ' + conf_line) self.instance_com.send_client_auth(client, client_conf) else: self.instance_com.send_client_deny( client, 'Unable to assign ip address') except: logger.exception('Error parsing client connect', 'server', server_id=self.server.id, ) self.instance_com.send_client_deny( client, 'Error parsing client connect')
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)