def _load_ip_pool(self): if cache_db.get(self.get_cache_key('ip_pool_cached')) == 't': return reset = False if os.path.exists(self.ip_pool_path): with open(self.ip_pool_path, 'r') as ip_pool_file: pool = json.loads(ip_pool_file.read()) network = pool.pop('network', None) if network == self.network: cache_key = self.get_cache_key('ip_pool') set_cache_key = self.get_cache_key('ip_pool_set') for key, value in pool.iteritems(): cache_db.dict_set(cache_key, key, value) local_ip_addr, remote_ip_addr = value.split('-') cache_db.set_add(set_cache_key, local_ip_addr) cache_db.set_add(set_cache_key, remote_ip_addr) else: reset = True cache_db.set(self.get_cache_key('ip_pool_cached'), 't') if reset: self.update_ip_pool()
def __getattr__(self, name): if name == 'web_protocol': if not self.ssl: return 'http' return 'https' elif name == 'password_data': if self.password[:2] == '1$': pass_split = self.password.split('$') return (1, pass_split[1], pass_split[2]) else: return (0, PASSWORD_SALT_V0, self.password) elif name == 'ssl': if self.debug: return False elif name == 'localhost_ip': localhost_ip = cache_db.get('localhost_ip') if not localhost_ip: try: localhost_ip = socket.gethostbyname('localhost') except: localhost_ip = '127.0.0.1' cache_db.expire('localhost_ip', LOCALHOST_IP_TTL) cache_db.set('localhost_ip', localhost_ip) return localhost_ip return Config.__getattr__(self, name)
def check_session(): from pritunl import app_server 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 try: if abs(int(auth_timestamp) - int(time.time())) > AUTH_TIME_WINDOW: return False except ValueError: return False cache_key = "auth_nonce-%s" % auth_nonce if cache_db.exists(cache_key): return False cache_db.expire(cache_key, int(AUTH_TIME_WINDOW * 2.1)) cache_db.set(cache_key, auth_timestamp) auth_token_hash = persist_db.dict_get("auth", "token") auth_secret = persist_db.dict_get("auth", "secret") if not auth_token_hash or not auth_secret: return False if not _test_password_hash(auth_token_hash, auth_token): 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(auth_secret.encode(), auth_string, hashlib.sha256).digest()) if auth_signature != auth_test_signature: return False else: if not flask.session: return False if not flask.session.get("auth"): flask.session.clear() return False if not app_server.ssl and flask.session.get("source") != get_remote_addr(): flask.session.clear() return False if app_server.session_timeout and int(time.time()) - flask.session["timestamp"] > app_server.session_timeout: flask.session.clear() return False return True
def _cache_orgs(cls): if cache_db.get('orgs_cached') != 't': cache_db.remove('orgs') path = os.path.join(app_server.data_path, ORGS_DIR) if os.path.isdir(path): for org_id in os.listdir(path): cache_db.set_add('orgs', org_id) cls.sort_orgs_cache() cache_db.set('orgs_cached', 't')
def _cache_orgs(cls): if cache_db.get("orgs_cached") != "t": cache_db.remove("orgs") path = os.path.join(app_server.data_path, ORGS_DIR) if os.path.isdir(path): for org_id in os.listdir(path): cache_db.set_add("orgs", org_id) cls.sort_orgs_cache() cache_db.set("orgs_cached", "t")
def load(self, merge=False): logger.debug('Loading config. %r' % { 'path': self._conf_path, }) self._loaded = True if self.cached: if not hasattr(self, 'id'): raise ValueError('Object ID is required for caching') if cache_db.get(self.get_cache_key('cached')) == 't': if merge: for name, value in cache_db.dict_get_all( self.get_cache_key()).iteritems(): if name in self.__dict__: continue self.__dict__[name] = value else: self.__dict__.update(cache_db.dict_get_all( self.get_cache_key())) return try: with open(self._conf_path) as config: for line in config: line = line.rstrip('\n') if line.strip() == '': continue elif line[0] == '#': continue elif '=' in line: pass else: logger.warning('Ignoring invalid line. %r' % { 'line': line, }) continue try: name, value = self._decode_line(line) if merge and name in self.__dict__: continue self.__dict__[name] = value if self.cached: cache_db.dict_set(self.get_cache_key(), name, value) except ValueError: logger.warning('Ignoring invalid line. %r' % { 'line': line, }) except IOError: if not merge: raise if self.cached: cache_db.set(self.get_cache_key('cached'), 't')
def load(self, merge=False): logger.debug('Loading config. %r' % { 'path': self._conf_path, }) self._loaded = True if self.cached: if not hasattr(self, 'id'): raise ValueError('Object ID is required for caching') if cache_db.get(self.get_cache_key('cached')) == 't': if merge: for name, value in cache_db.dict_get_all( self.get_cache_key()).iteritems(): if name in self.__dict__: continue self.__dict__[name] = value else: self.__dict__.update( cache_db.dict_get_all(self.get_cache_key())) return try: with open(self._conf_path) as config: for line in config: line = line.rstrip('\n') if line.strip() == '': continue elif line[0] == '#': continue elif '=' in line: pass else: logger.warning('Ignoring invalid line. %r' % { 'line': line, }) continue try: name, value = self._decode_line(line) if merge and name in self.__dict__: continue self.__dict__[name] = value if self.cached: cache_db.dict_set(self.get_cache_key(), name, value) except ValueError: logger.warning('Ignoring invalid line. %r' % { 'line': line, }) except IOError: if not merge: raise if self.cached: cache_db.set(self.get_cache_key('cached'), 't')
def sort_users_cache(self): user_count = 0 users_dict = {} users_sort = [] # Create temp uuid key to prevent multiple threads modifying same key temp_suffix = 'temp_' + uuid.uuid4().hex temp_users_sorted_key = 'users_sorted_' + temp_suffix users_page_index_key = 'users_page_index_' + temp_suffix try: for user_id in cache_db.set_elements(self.get_cache_key('users')): user = User.get_user(self, id=user_id) if not user: continue name_id = '%s_%s' % (user.name, user_id) if user.type == CERT_CLIENT: user_count += 1 users_dict[name_id] = (user_id, user.type) users_sort.append(name_id) cache_db.set(self.get_cache_key('user_count'), str(user_count)) cur_page = 0 user_count = 0 client_count = 0 for name_id in sorted(users_sort): if users_dict[name_id][1] == CERT_CLIENT: page = client_count / USER_PAGE_COUNT if page != cur_page: cur_page = page cache_db.dict_set(self.get_cache_key(users_page_index_key), str(cur_page), str(user_count)) client_count += 1 user_count += 1 cache_db.list_rpush(self.get_cache_key(temp_users_sorted_key), users_dict[name_id][0]) cache_db.lock_acquire(self.get_cache_key('sort')) try: cache_db.rename(self.get_cache_key(users_page_index_key), self.get_cache_key('users_page_index')) cache_db.rename(self.get_cache_key(temp_users_sorted_key), self.get_cache_key('users_sorted')) cache_db.set(self.get_cache_key('users_page_total'), str(cur_page)) finally: cache_db.lock_release(self.get_cache_key('sort')) except: cache_db.remove(self.get_cache_key(users_page_index_key)) cache_db.remove(self.get_cache_key(temp_users_sorted_key)) raise
def _cache_servers(cls): if cache_db.get('servers_cached') != 't': cache_db.remove('servers') path = os.path.join(app_server.data_path, SERVERS_DIR) if os.path.isdir(path): for server_id in os.listdir(path): if os.path.isfile(os.path.join(path, server_id, NODE_SERVER)): server_id += '_' + NODE_SERVER else: server_id += '_' + SERVER cache_db.set_add('servers', server_id) cls.sort_servers_cache() cache_db.set('servers_cached', 't')
def _cache_users(self): if cache_db.get(self.get_cache_key('users_cached')) != 't': cache_db.remove(self.get_cache_key('users')) certs_path = os.path.join(self.path, CERTS_DIR) if os.path.isdir(certs_path): for cert in os.listdir(certs_path): user_id = cert.replace('.crt', '') if user_id == CA_CERT_ID: continue user = User.get_user(self, id=user_id) if not user: continue user._add_cache_trie_key() cache_db.set_add(self.get_cache_key('users'), user_id) self.sort_users_cache() cache_db.set(self.get_cache_key('users_cached'), 't')
def verify_otp_code(self, code, remote_ip=None): if remote_ip: otp_cache = cache_db.get(self.get_cache_key('otp_cache')) if otp_cache: cur_code, cur_remote_ip = otp_cache.split(',') if cur_code == code and cur_remote_ip == remote_ip: cache_db.expire(self.get_cache_key('otp_cache'), OTP_CACHE_TTL) return True else: cache_db.remove(self.get_cache_key('otp_cache')) otp_secret = self.otp_secret padding = 8 - len(otp_secret) % 8 if padding != 8: otp_secret = otp_secret.ljust(len(otp_secret) + padding, '=') otp_secret = base64.b32decode(otp_secret.upper()) valid_codes = [] epoch = int(time.time() / 30) for epoch_offset in range(-1, 2): value = struct.pack('>q', epoch + epoch_offset) hmac_hash = hmac.new(otp_secret, value, hashlib.sha1).digest() offset = ord(hmac_hash[-1]) & 0x0F truncated_hash = hmac_hash[offset:offset + 4] truncated_hash = struct.unpack('>L', truncated_hash)[0] truncated_hash &= 0x7FFFFFFF truncated_hash %= 1000000 valid_codes.append('%06d' % truncated_hash) if code not in valid_codes: return False used_codes = cache_db.dict_get_all(self.get_cache_key('otp')) for auth_time, used_code in used_codes.items(): if int(time.time()) - int(auth_time) > 120: cache_db.dict_remove(self.get_cache_key('otp'), auth_time) if used_code == code: return False cache_db.dict_set(self.get_cache_key('otp'), str(int(time.time())), code) cache_db.expire(self.get_cache_key('otp_cache'), OTP_CACHE_TTL) cache_db.set(self.get_cache_key('otp_cache'), ','.join((code, remote_ip))) return True
def sort_orgs_cache(cls): org_count = 0 orgs_dict = {} orgs_sort = [] # Create temp uuid key to prevent multiple threads modifying same key temp_orgs_sorted_key = 'orgs_sorted_temp_' + uuid.uuid4().hex try: for org_id in cache_db.set_elements('orgs'): org = Organization.get_org(id=org_id) if not org: continue name_id = '%s_%s' % (org.name, org_id) org_count += 1 orgs_dict[name_id] = org_id orgs_sort.append(name_id) cache_db.set('org_count', str(org_count)) for name_id in sorted(orgs_sort): cache_db.list_rpush(temp_orgs_sorted_key, orgs_dict[name_id]) cache_db.rename(temp_orgs_sorted_key, 'orgs_sorted') except: cache_db.remove(temp_orgs_sorted_key) raise
def check_session(): from administrator import Administrator 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(time.time())) > AUTH_TIME_WINDOW: return False except ValueError: return False # TODO cache_key = 'auth_nonce-%s' % auth_nonce if cache_db.exists(cache_key): return False administrator = 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 # TODO cache_db.expire(cache_key, int(AUTH_TIME_WINDOW * 2.1)) cache_db.set(cache_key, auth_timestamp) flask.request.administrator = administrator else: from pritunl import app_server if not flask.session: return False admin_id = flask.session.get('admin_id') if not admin_id: return False administrator = Administrator.get_user(id=admin_id) if not administrator: return False if not app_server.ssl and flask.session.get( 'source') != get_remote_addr(): flask.session.clear() return False if SESSION_TIMEOUT and int(time.time()) - \ flask.session['timestamp'] > SESSION_TIMEOUT: flask.session.clear() return False flask.request.administrator = administrator return True
def check_session(): from pritunl import app_server auth_valid = True 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(time.time())) > AUTH_TIME_WINDOW: return False except ValueError: return False cache_key = 'auth_nonce-%s' % auth_nonce if cache_db.exists(cache_key): return False auth_token_hash = persist_db.dict_get('auth', 'token') auth_secret = persist_db.dict_get('auth', 'secret') if not auth_token_hash or not auth_secret: return False if not _test_password_hash(auth_token_hash, auth_token): auth_valid = 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( auth_secret.encode(), auth_string, hashlib.sha256).digest()) if auth_signature != auth_test_signature: auth_valid = False if auth_valid: cache_db.expire(cache_key, int(AUTH_TIME_WINDOW * 2.1)) cache_db.set(cache_key, auth_timestamp) else: if not flask.session: return False if not flask.session.get('auth'): flask.session.clear() return False if not app_server.ssl and flask.session.get( 'source') != get_remote_addr(): flask.session.clear() return False if app_server.session_timeout and int(time.time()) - \ flask.session['timestamp'] > app_server.session_timeout: flask.session.clear() return False return auth_valid