Esempio n. 1
0
    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()
Esempio n. 2
0
 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)
Esempio n. 3
0
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
Esempio n. 4
0
 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')
Esempio n. 5
0
 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")
Esempio n. 6
0
    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')
Esempio n. 7
0
    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')
Esempio n. 8
0
    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
Esempio n. 9
0
 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')
Esempio n. 10
0
 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')
Esempio n. 11
0
    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
Esempio n. 12
0
    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
Esempio n. 13
0
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
Esempio n. 14
0
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