Beispiel #1
0
def server_host_put(server_id, host_id):
    if settings.app.demo_mode:
        return utils.demo_blocked()

    svr = server.get_by_id(server_id)
    if not svr:
        return flask.abort(404)
    hst = host.get_by_id(host_id,
                         fields=('_id', 'name', 'public_address',
                                 'auto_public_address', 'auto_public_host',
                                 'public_address6', 'auto_public_address6',
                                 'auto_public_host6'))
    if not svr:
        return flask.abort(404)

    try:
        svr.add_host(hst.id)
    except ServerLinkCommonHostError:
        return utils.jsonify(
            {
                'error': SERVER_LINK_COMMON_HOST,
                'error_msg': SERVER_LINK_COMMON_HOST_MSG,
            }, 400)

    err, err_msg = svr.validate_conf(allow_online=True)
    if err:
        return utils.jsonify({
            'error': err,
            'error_msg': err_msg,
        }, 400)

    svr.commit('hosts')
    event.Event(type=SERVER_HOSTS_UPDATED, resource_id=svr.id)

    return utils.jsonify({
        'id': hst.id,
        'server': svr.id,
        'status': OFFLINE,
        'name': hst.name,
        'address': hst.public_addr,
    })
Beispiel #2
0
def link_post():
    if settings.local.sub_plan != 'enterprise_plus':
        return flask.abort(404)

    if settings.app.demo_mode:
        return utils.demo_blocked()

    name = utils.filter_str(flask.request.json.get('name')) or 'undefined'

    lnk = link.Link(
        name=name,
        status=ONLINE,
    )

    lnk.generate_key()

    lnk.commit()

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify(lnk.dict())
Beispiel #3
0
def link_location_host_delete(link_id, location_id, host_id):
    if settings.app.demo_mode:
        return utils.demo_blocked()

    lnk = link.get_by_id(link_id)
    if not lnk:
        return flask.abort(404)

    loc = lnk.get_location(location_id)
    if not loc:
        return flask.abort(404)

    hst = loc.get_host(host_id)
    if not hst:
        return flask.abort(404)

    hst.remove()

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify({})
Beispiel #4
0
def link_location_delete(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)

    loc.remove()

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify({})
Beispiel #5
0
def init():
    settings.local.host = Host()

    try:
        settings.local.host.load()
    except NotFound:
        pass

    settings.local.host.status = ONLINE
    settings.local.host.users_online = 0
    settings.local.host.start_timestamp = utils.now()
    settings.local.host.ping_timestamp = utils.now()
    if settings.local.public_ip:
        settings.local.host.auto_public_address = settings.local.public_ip

    try:
        settings.local.host.hostname = socket.gethostname()
    except:
        logger.exception('Failed to get hostname', 'host')
        settings.local.host.hostname = None

    if settings.conf.local_address_interface == 'auto':
        try:
            settings.local.host.local_address = socket.gethostbyname(
                socket.gethostname())
        except:
            logger.exception('Failed to get local_address auto', 'host')
            settings.local.host.local_address = None
    else:
        try:
            settings.local.host.local_address = utils.get_interface_address(
                str(settings.conf.local_address_interface))
        except:
            logger.exception('Failed to get local_address',
                             'host',
                             interface=settings.conf.local_address_interface)
            settings.local.host.local_address = None

    settings.local.host.commit()
    event.Event(type=HOSTS_UPDATED)
Beispiel #6
0
def link_location_route_delete(link_id, location_id, network):
    if settings.local.sub_plan != 'enterprise_plus':
        return flask.abort(404)

    if settings.app.demo_mode:
        return utils.demo_blocked()

    lnk = link.get_by_id(link_id)
    if not lnk:
        return flask.abort(404)

    loc = lnk.get_location(location_id)
    if not loc:
        return flask.abort(404)

    loc.remove_route(network)

    loc.commit('routes')

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify({})
Beispiel #7
0
def link_put(link_id):
    if settings.local.sub_plan != 'enterprise_plus':
        return flask.abort(404)

    if settings.app.demo_mode:
        return utils.demo_blocked()

    lnk = link.get_by_id(link_id)
    if not lnk:
        return flask.abort(404)

    lnk.name = utils.filter_str(flask.request.json.get('name')) or 'undefined'

    status = flask.request.json.get('status')
    if status in (ONLINE, OFFLINE):
        lnk.status = status

    lnk.commit(('name', 'status'))

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify(lnk.dict())
Beispiel #8
0
def link_location_put(link_id, location_id):
    if settings.local.sub_plan != 'enterprise_plus':
        return flask.abort(404)

    if settings.app.demo_mode:
        return utils.demo_blocked()

    lnk = link.get_by_id(link_id)
    if not lnk:
        return flask.abort(404)

    loc = lnk.get_location(location_id)
    if not loc:
        return flask.abort(404)

    loc.name = utils.filter_str(flask.request.json.get('name')) or 'undefined'

    loc.commit('name')

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify(loc.dict())
Beispiel #9
0
def link_put(link_id):
    if not settings.local.sub_plan or \
            'enterprise' not in settings.local.sub_plan:
        return flask.abort(404)

    if settings.app.demo_mode:
        return utils.demo_blocked()

    lnk = link.get_by_id(link_id)
    if not lnk:
        return flask.abort(404)

    lnk.name = utils.filter_str(flask.request.json.get('name')) or 'undefined'

    status = flask.request.json.get('status')
    if status in (ONLINE, OFFLINE):
        lnk.status = status

    if flask.request.json.get('key'):
        lnk.generate_key()

    lnk.ipv6 = True if flask.request.json.get('ipv6') else False

    lnk.host_check = True if flask.request.json.get('host_check') else False

    lnk.action = RESTART if flask.request.json.get(
        'action') == RESTART else HOLD

    lnk.preferred_ike = utils.filter_str(
        flask.request.json.get('preferred_ike')) or None
    lnk.preferred_esp = utils.filter_str(
        flask.request.json.get('preferred_esp')) or None

    lnk.commit(('name', 'status', 'key', 'ipv6', 'host_check', 'action',
                'preferred_ike', 'preferred_esp'))

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify(lnk.dict())
Beispiel #10
0
def server_host_put(server_id, host_id):
    svr = server.get_by_id(server_id, fields=('_id', 'hosts', 'links'))
    hst = host.get_by_id(host_id, fields=('_id', 'name',
        'public_address', 'auto_public_address'))

    try:
        svr.add_host(hst.id)
    except ServerLinkCommonHostError:
        return utils.jsonify({
            'error': SERVER_LINK_COMMON_HOST,
            'error_msg': SERVER_LINK_COMMON_HOST_MSG,
        }, 400)

    svr.commit('hosts')
    event.Event(type=SERVER_HOSTS_UPDATED, resource_id=svr.id)

    return utils.jsonify({
        'id': hst.id,
        'server': svr.id,
        'status': OFFLINE,
        'name': hst.name,
        'address': hst.public_addr,
    })
Beispiel #11
0
def link_location_host_put(link_id, location_id, host_id):
    if settings.app.demo_mode:
        return utils.demo_blocked()

    lnk = link.get_by_id(link_id)
    if not lnk:
        return flask.abort(404)

    loc = lnk.get_location(location_id)
    if not loc:
        return flask.abort(404)

    hst = loc.get_host(host_id)
    if not hst:
        return flask.abort(404)

    hst.name = utils.filter_str(flask.request.json.get('name')) or 'undefined'

    hst.commit('name')

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify(hst.dict())
Beispiel #12
0
def admin_delete(admin_id):
    if settings.app.demo_mode:
        return utils.demo_blocked()

    if not flask.g.administrator.super_user:
        return utils.jsonify(
            {
                'error': REQUIRES_SUPER_USER,
                'error_msg': REQUIRES_SUPER_USER_MSG,
            }, 400)

    admin = auth.get_by_id(admin_id)

    if admin.super_user and auth.super_user_count() < 2:
        return utils.jsonify({
            'error': NO_ADMINS,
            'error_msg': NO_ADMINS_MSG,
        }, 400)

    admin.remove()
    event.Event(type=ADMINS_UPDATED)

    return utils.jsonify({})
Beispiel #13
0
def link_location_host_post(link_id, location_id):
    if not settings.local.sub_plan or \
            'enterprise' not in settings.local.sub_plan:
        return flask.abort(404)

    if settings.app.demo_mode:
        return utils.demo_blocked()

    lnk = link.get_by_id(link_id)
    if not lnk:
        return flask.abort(404)

    loc = lnk.get_location(location_id)
    if not loc:
        return flask.abort(404)

    name = utils.filter_str(flask.request.json.get('name')) or 'undefined'
    timeout = int(flask.request.json.get('timeout') or 0) or None
    priority = abs(int(flask.request.json.get('priority') or 1)) or 1

    hst = link.Host(
        link=lnk,
        location=loc,
        link_id=lnk.id,
        location_id=loc.id,
        name=name,
        timeout=timeout,
        priority=priority,
    )

    hst.generate_secret()

    hst.commit()

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify(hst.dict())
Beispiel #14
0
def link_location_peer_delete(link_id, location_id, peer_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)

    loc.add_exclude(peer_id)

    lnk.commit('excludes')
    loc.commit('transit_excludes')

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify({})
Beispiel #15
0
def link_location_peer_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)

    peer_id = utils.ObjectId(flask.request.json.get('peer_id'))
    loc.remove_exclude(peer_id)

    lnk.commit('excludes')

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify({})
Beispiel #16
0
def link_location_transit_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)

    transit_id = database.ParseObjectId(flask.request.json.get('transit_id'))
    loc.add_transit(transit_id)

    loc.commit('transits')

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify({})
Beispiel #17
0
def link_location_host_put(link_id, location_id, host_id):
    if not settings.local.sub_plan or \
            'enterprise' not in settings.local.sub_plan:
        return flask.abort(404)

    if settings.app.demo_mode:
        return utils.demo_blocked()

    lnk = link.get_by_id(link_id)
    if not lnk:
        return flask.abort(404)

    loc = lnk.get_location(location_id)
    if not loc:
        return flask.abort(404)

    hst = loc.get_host(host_id)
    if not hst:
        return flask.abort(404)

    hst.name = utils.filter_str(flask.request.json.get('name')) or 'undefined'
    hst.timeout = abs(int(flask.request.json.get('timeout') or 0)) or None
    hst.priority = abs(int(flask.request.json.get('priority') or 1)) or 1
    hst.backoff = abs(int(flask.request.json.get('backoff') or 0)) or None
    hst.static = bool(flask.request.json.get('static'))
    hst.public_address = utils.filter_str(
        flask.request.json.get('public_address'))
    hst.local_address = utils.filter_str(
        flask.request.json.get('local_address'))

    hst.commit(('name', 'timeout', 'priority', 'backoff', 'static',
                'public_address', 'local_address'))

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify(hst.dict())
Beispiel #18
0
def link_location_post(link_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)

    name = utils.filter_str(flask.request.json.get('name')) or 'undefined'

    loc = link.Location(
        link=lnk,
        name=name,
        link_id=lnk.id,
    )
    loc.commit()

    event.Event(type=LINKS_UPDATED)

    return utils.jsonify(loc.dict())
Beispiel #19
0
 def send_link_events(self):
     event.Event(type=SERVER_LINKS_UPDATED, resource_id=self.id)
     for link in self.links:
         event.Event(type=SERVER_LINKS_UPDATED,
                     resource_id=link['server_id'])
Beispiel #20
0
def _auth_plugin(username, password):
    if settings.local.sub_plan != 'enterprise':
        return utils.jsonify({
            'error': AUTH_INVALID,
            'error_msg': AUTH_INVALID_MSG,
        }, 401)

    valid, org_id, groups = sso.plugin_login_authenticate(
        user_name=username,
        password=password,
        remote_ip=utils.get_remote_addr(),
    )

    if not valid:
        return utils.jsonify({
            'error': AUTH_INVALID,
            'error_msg': AUTH_INVALID_MSG,
        }, 401)

    if not org_id:
        logger.error(
            'Login plugin did not return valid organization name',
            'auth',
            org_name=org_id,
            user_name=username,
        )
        return utils.jsonify({
            'error': AUTH_INVALID,
            'error_msg': AUTH_INVALID_MSG,
        }, 401)

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(405)

    usr = org.find_user(name=username)
    if not usr:
        usr = org.new_user(name=username, type=CERT_CLIENT,
            auth_type=PLUGIN_AUTH, groups=list(groups) if groups else None)
        usr.audit_event(
            'user_created',
            'User created with plugin authentication',
            remote_addr=utils.get_remote_addr(),
        )

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if usr.disabled:
            return utils.jsonify({
                'error': AUTH_DISABLED,
                'error_msg': AUTH_DISABLED_MSG,
            }, 403)

        if groups and groups - set(usr.groups or []):
            usr.groups = list(set(usr.groups or []) | groups)
            usr.commit('groups')

        if usr.auth_type != PLUGIN_AUTH:
            usr.auth_type = PLUGIN_AUTH
            usr.set_pin(None)
            usr.commit(('auth_type', 'pin'))

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event('user_profile',
        'User profile viewed from plugin authentication',
        remote_addr=utils.get_remote_addr(),
    )

    return utils.jsonify({
        'redirect': utils.get_url_root() + key_link['view_url'],
    }, 202)
Beispiel #21
0
def _auth_radius(username, password):
    sso_mode = settings.app.sso

    valid, org_names, groups = sso.verify_radius(username, password)
    if not valid:
        return utils.jsonify({
            'error': AUTH_INVALID,
            'error_msg': AUTH_INVALID_MSG,
        }, 401)

    org_id = settings.app.sso_org
    if org_names:
        for org_name in org_names:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id
                break

    valid, org_id_new, groups2 = sso.plugin_sso_authenticate(
        sso_type='radius',
        user_name=username,
        user_email=None,
        remote_ip=utils.get_remote_addr(),
    )
    if valid:
        org_id = org_id_new or org_id
    else:
        logger.error('Radius plugin authentication not valid', 'sso',
            username=username,
        )
        return utils.jsonify({
            'error': AUTH_INVALID,
            'error_msg': AUTH_INVALID_MSG,
        }, 401)

    groups = ((groups or set()) | (groups2 or set())) or None

    if DUO_AUTH in sso_mode:
        try:
            duo_auth = sso.Duo(
                username=username,
                factor=settings.app.sso_duo_mode,
                remote_ip=utils.get_remote_addr(),
                auth_type='Key',
            )
            valid = duo_auth.authenticate()
        except InvalidUser:
            logger.error('Duo authentication username not valid', 'sso',
                username=username,
            )
            return utils.jsonify({
                'error': AUTH_INVALID,
                'error_msg': AUTH_INVALID_MSG,
            }, 401)
        if valid:
            valid, org_id_new, groups2 = sso.plugin_sso_authenticate(
                sso_type='duo',
                user_name=username,
                user_email=None,
                remote_ip=utils.get_remote_addr(),
            )
            if valid:
                org_id = org_id_new or org_id
            else:
                logger.error('Duo plugin authentication not valid', 'sso',
                    username=username,
                )
                return utils.jsonify({
                    'error': AUTH_INVALID,
                    'error_msg': AUTH_INVALID_MSG,
                }, 401)

            groups = ((groups or set()) | (groups2 or set())) or None
        else:
            logger.error('Duo authentication not valid', 'sso',
                username=username,
            )
            return utils.jsonify({
                'error': AUTH_INVALID,
                'error_msg': AUTH_INVALID_MSG,
            }, 401)

    groups = ((groups or set()) | (groups2 or set())) or None

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(405)

    usr = org.find_user(name=username)
    if not usr:
        usr = org.new_user(name=username, type=CERT_CLIENT,
            auth_type=sso_mode, groups=list(groups) if groups else None)

        usr.audit_event(
            'user_created',
            'User created with single sign-on',
            remote_addr=utils.get_remote_addr(),
        )

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if usr.disabled:
            return utils.jsonify({
                'error': AUTH_DISABLED,
                'error_msg': AUTH_DISABLED_MSG,
            }, 403)

        if groups and groups - set(usr.groups or []):
            usr.groups = list(set(usr.groups or []) | groups)
            usr.commit('groups')

        if usr.auth_type != sso_mode:
            usr.auth_type = sso_mode
            usr.set_pin(None)
            usr.commit(('auth_type', 'pin'))

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event('user_profile',
        'User profile viewed from single sign-on',
        remote_addr=utils.get_remote_addr(),
    )

    return utils.jsonify({
        'redirect': utils.get_url_root() + key_link['view_url'],
    }, 202)
Beispiel #22
0
    def _run_thread(self, send_events):
        from pritunl.server.utils import get_by_id

        logger.debug(
            'Starting ovpn process',
            'server',
            server_id=self.server.id,
        )

        self.resources_acquire()
        try:
            cursor_id = self.get_cursor_id()

            os.makedirs(self._temp_path)
            self.generate_ovpn_conf()

            self.enable_ip_forwarding()
            self.set_iptables_rules()

            self.process = self.openvpn_start()
            if not self.process:
                return

            self.start_threads(cursor_id)

            self.instance_com = ServerInstanceCom(self.server, self)
            self.instance_com.start()

            self.publish('started')

            if send_events:
                event.Event(type=SERVERS_UPDATED)
                event.Event(type=SERVER_HOSTS_UPDATED,
                            resource_id=self.server.id)
                for org_id in self.server.organizations:
                    event.Event(type=USERS_UPDATED, resource_id=org_id)

            for link_doc in self.server.links:
                if self.server.id > link_doc['server_id']:
                    instance_link = ServerInstanceLink(
                        server=self.server,
                        linked_server=get_by_id(link_doc['server_id']),
                    )
                    self.server_links.append(instance_link)
                    instance_link.start()

            self.openvpn_watch()

            self.interrupt = True
            self.clear_iptables_rules()
            self.resources_release()

            if not self.clean_exit:
                event.Event(type=SERVERS_UPDATED)
                self.server.send_link_events()
                logger.LogEntry(message='Server stopped unexpectedly "%s".' %
                                (self.server.name))
        except:
            self.interrupt = True
            if self.resource_lock:
                self.clear_iptables_rules()
            self.resources_release()

            logger.exception(
                'Server error occurred while running',
                'server',
                server_id=self.server.id,
            )
        finally:
            self.stop_threads()
            self.collection.update(
                {
                    '_id': self.server.id,
                    'instances.instance_id': self.id,
                }, {
                    '$pull': {
                        'instances': {
                            'instance_id': self.id,
                        },
                    },
                    '$inc': {
                        'instances_count': -1,
                    },
                })
            utils.rmtree(self._temp_path)
Beispiel #23
0
 def send_event(self):
     for org_id in self.server.organizations:
         event.Event(type=USERS_UPDATED, resource_id=org_id)
     event.Event(type=HOSTS_UPDATED, resource_id=settings.local.host_id)
     event.Event(type=SERVERS_UPDATED)
Beispiel #24
0
 def repeat_task(self):
     event.Event(type=ORGS_UPDATED)
Beispiel #25
0
def server_put_post(server_id=None):
    if settings.app.demo_mode:
        return utils.demo_blocked()

    used_resources = server.get_used_resources(server_id)
    network_used = used_resources['networks']
    port_used = used_resources['ports']

    name = None
    name_def = False
    if 'name' in flask.request.json:
        name_def = True
        name = utils.filter_str(flask.request.json['name'])

    network = None
    network_def = False
    if 'network' in flask.request.json:
        network_def = True
        network = flask.request.json['network']

        try:
            if not _check_network_private(network):
                return _network_invalid()
        except (ipaddress.AddressValueError, ValueError):
            return _network_invalid()

    network_mode = None
    network_mode_def = False
    if 'network_mode' in flask.request.json:
        network_mode_def = True
        network_mode = flask.request.json['network_mode']

    network_start = None
    network_start_def = False
    if 'network_start' in flask.request.json:
        network_start_def = True
        network_start = flask.request.json['network_start']

    network_end = None
    network_end_def = False
    if 'network_end' in flask.request.json:
        network_end_def = True
        network_end = flask.request.json['network_end']

    restrict_routes = None
    restrict_routes_def = False
    if 'restrict_routes' in flask.request.json:
        restrict_routes_def = True
        restrict_routes = True if flask.request.json['restrict_routes'] \
            else False

    ipv6 = None
    ipv6_def = False
    if 'ipv6' in flask.request.json:
        ipv6_def = True
        ipv6 = True if flask.request.json['ipv6'] else False

    ipv6_firewall = None
    ipv6_firewall_def = False
    if 'ipv6_firewall' in flask.request.json:
        ipv6_firewall_def = True
        ipv6_firewall = True if flask.request.json['ipv6_firewall'] else False

    bind_address = None
    bind_address_def = False
    if 'bind_address' in flask.request.json:
        bind_address_def = True
        bind_address = utils.filter_str(flask.request.json['bind_address'])

    protocol = 'udp'
    protocol_def = False
    if 'protocol' in flask.request.json:
        protocol_def = True
        protocol = flask.request.json['protocol'].lower()

        if protocol not in ('udp', 'tcp'):
            return utils.jsonify({
                'error': PROTOCOL_INVALID,
                'error_msg': PROTOCOL_INVALID_MSG,
            }, 400)

    port = None
    port_def = False
    if 'port' in flask.request.json:
        port_def = True
        port = flask.request.json['port']

        try:
            port = int(port)
        except ValueError:
            return _port_invalid()

        if port < 1 or port > 65535:
            return _port_invalid()

    dh_param_bits = None
    dh_param_bits_def = False
    if flask.request.json.get('dh_param_bits'):
        dh_param_bits_def = True
        dh_param_bits = flask.request.json['dh_param_bits']

        try:
            dh_param_bits = int(dh_param_bits)
        except ValueError:
            return _dh_param_bits_invalid()

        if dh_param_bits not in VALID_DH_PARAM_BITS:
            return _dh_param_bits_invalid()

    multi_device = False
    multi_device_def = False
    if 'multi_device' in flask.request.json:
        multi_device_def = True
        multi_device = True if flask.request.json['multi_device'] else False

    dns_servers = None
    dns_servers_def = False
    if 'dns_servers' in flask.request.json:
        dns_servers_def = True
        dns_servers = flask.request.json['dns_servers'] or []

        for dns_server in dns_servers:
            try:
                ipaddress.IPAddress(dns_server)
            except (ipaddress.AddressValueError, ValueError):
                return _dns_server_invalid()

    search_domain = None
    search_domain_def = False
    if 'search_domain' in flask.request.json:
        search_domain_def = True
        search_domain = utils.filter_str(flask.request.json['search_domain'])

    inter_client = True
    inter_client_def = False
    if 'inter_client' in flask.request.json:
        inter_client_def = True
        inter_client = True if flask.request.json['inter_client'] else False

    ping_interval = None
    ping_interval_def = False
    if 'ping_interval' in flask.request.json:
        ping_interval_def = True
        ping_interval = flask.request.json['ping_interval']
        if ping_interval:
            ping_interval = int(ping_interval)
        if not ping_interval:
            ping_interval = 10

    ping_timeout = None
    ping_timeout_def = False
    if 'ping_timeout' in flask.request.json:
        ping_timeout_def = True
        ping_timeout = flask.request.json['ping_timeout']
        if ping_timeout:
            ping_timeout = int(ping_timeout)
        if not ping_timeout:
            ping_timeout = 60

    link_ping_interval = None
    link_ping_interval_def = False
    if 'link_ping_interval' in flask.request.json:
        link_ping_interval_def = True
        link_ping_interval = flask.request.json['link_ping_interval']
        if link_ping_interval:
            link_ping_interval = int(link_ping_interval)
        if not link_ping_interval:
            link_ping_interval = 1

    link_ping_timeout = None
    link_ping_timeout_def = False
    if 'link_ping_timeout' in flask.request.json:
        link_ping_timeout_def = True
        link_ping_timeout = flask.request.json['link_ping_timeout']
        if link_ping_timeout:
            link_ping_timeout = int(link_ping_timeout)
        if not link_ping_timeout:
            link_ping_timeout = 5

    onc_hostname = None
    onc_hostname_def = False
    if 'onc_hostname' in flask.request.json:
        onc_hostname_def = True
        onc_hostname = utils.filter_str(flask.request.json['onc_hostname'])

    max_clients = None
    max_clients_def = False
    if 'max_clients' in flask.request.json:
        max_clients_def = True
        max_clients = flask.request.json['max_clients']
        if max_clients:
            max_clients = int(max_clients)
        if not max_clients:
            max_clients = 2000

    replica_count = None
    replica_count_def = False
    if 'replica_count' in flask.request.json:
        replica_count_def = True
        replica_count = flask.request.json['replica_count']
        if replica_count:
            replica_count = int(replica_count)
        if not replica_count:
            replica_count = 1

    dns_mapping = False
    dns_mapping_def = False
    if 'dns_mapping' in flask.request.json:
        dns_mapping_def = True
        dns_mapping = True if flask.request.json['dns_mapping'] else False

    debug = False
    debug_def = False
    if 'debug' in flask.request.json:
        debug_def = True
        debug = True if flask.request.json['debug'] else False

    otp_auth = False
    otp_auth_def = False
    if 'otp_auth' in flask.request.json:
        otp_auth_def = True
        otp_auth = True if flask.request.json['otp_auth'] else False

    lzo_compression = False
    lzo_compression_def = False
    if 'lzo_compression' in flask.request.json:
        lzo_compression_def = True
        lzo_compression = True if flask.request.json[
            'lzo_compression'] else False

    cipher = None
    cipher_def = False
    if 'cipher' in flask.request.json:
        cipher_def = True
        cipher = flask.request.json['cipher']

        if cipher not in CIPHERS:
            return utils.jsonify({
                'error': CIPHER_INVALID,
                'error_msg': CIPHER_INVALID_MSG,
            }, 400)

    hash = None
    hash_def = False
    if 'hash' in flask.request.json:
        hash_def = True
        hash = flask.request.json['hash']

        if hash not in HASHES:
            return utils.jsonify({
                'error': HASH_INVALID,
                'error_msg': HASH_INVALID_MSG,
            }, 400)

    jumbo_frames = False
    jumbo_frames_def = False
    if 'jumbo_frames' in flask.request.json:
        jumbo_frames_def = True
        jumbo_frames = True if flask.request.json[
            'jumbo_frames'] else False

    if not server_id:
        if not name_def:
            return utils.jsonify({
                'error': MISSING_PARAMS,
                'error_msg': MISSING_PARAMS_MSG,
            }, 400)

        if network_def and network_mode == BRIDGE and \
                (not network_start or not network_end):
            return utils.jsonify({
                'error': MISSING_PARAMS,
                'error_msg': MISSING_PARAMS_MSG,
            }, 400)

        if not network_def:
            network_def = True
            rand_range = range(215, 250)
            rand_range_low = range(15, 215)
            random.shuffle(rand_range)
            random.shuffle(rand_range_low)
            rand_range += rand_range_low
            for i in rand_range:
                rand_network = '192.168.%s.0/24' % i
                if not _check_network_overlap(rand_network, network_used):
                    network = rand_network
                    break
            if not network:
                return utils.jsonify({
                    'error': NETWORK_IN_USE,
                    'error_msg': NETWORK_IN_USE_MSG,
                }, 400)

        if not port_def:
            port_def = True
            rand_ports = range(10000, 19999)
            random.shuffle(rand_ports)
            for rand_port in rand_ports:
                if '%s%s' % (rand_port, protocol) not in port_used:
                    port = rand_port
                    break
            if not port:
                return utils.jsonify({
                    'error': PORT_PROTOCOL_IN_USE,
                    'error_msg': PORT_PROTOCOL_IN_USE_MSG,
                }, 400)

        if not dh_param_bits_def:
            dh_param_bits_def = True
            dh_param_bits = settings.vpn.default_dh_param_bits

    if network_def:
        if _check_network_overlap(network, network_used):
            return utils.jsonify({
                'error': NETWORK_IN_USE,
                'error_msg': NETWORK_IN_USE_MSG,
            }, 400)

    if port_def:
        if '%s%s' % (port, protocol) in port_used:
            return utils.jsonify({
                'error': PORT_PROTOCOL_IN_USE,
                'error_msg': PORT_PROTOCOL_IN_USE_MSG,
            }, 400)

    if not server_id:
        if network_mode == BRIDGE:
            if not _check_network_range(network, network_start, network_end):
                return utils.jsonify({
                    'error': BRIDGE_NETWORK_INVALID,
                    'error_msg': BRIDGE_NETWORK_INVALID_MSG,
                }, 400)

            if ipv6:
                return utils.jsonify({
                    'error': IPV6_BRIDGED_INVALID,
                    'error_msg': IPV6_BRIDGED_INVALID_MSG,
                }, 400)

        svr = server.new_server(
            name=name,
            network=network,
            network_mode=network_mode,
            network_start=network_start,
            network_end=network_end,
            restrict_routes=restrict_routes,
            ipv6=ipv6,
            ipv6_firewall=ipv6_firewall,
            bind_address=bind_address,
            port=port,
            protocol=protocol,
            dh_param_bits=dh_param_bits,
            multi_device=multi_device,
            dns_servers=dns_servers,
            search_domain=search_domain,
            otp_auth=otp_auth,
            cipher=cipher,
            hash=hash,
            jumbo_frames=jumbo_frames,
            lzo_compression=lzo_compression,
            inter_client=inter_client,
            ping_interval=ping_interval,
            ping_timeout=ping_timeout,
            link_ping_interval=link_ping_interval,
            link_ping_timeout=link_ping_timeout,
            onc_hostname=onc_hostname,
            max_clients=max_clients,
            replica_count=replica_count,
            dns_mapping=dns_mapping,
            debug=debug,
        )
        svr.add_host(settings.local.host_id)
        svr.commit()
    else:
        svr = server.get_by_id(server_id)
        if svr.status == ONLINE:
            return utils.jsonify({
                'error': SERVER_NOT_OFFLINE,
                'error_msg': SERVER_NOT_OFFLINE_SETTINGS_MSG,
            }, 400)

        for link_svr in svr.iter_links(fields=('status',)):
            if link_svr.status == ONLINE:
                return utils.jsonify({
                    'error': SERVER_LINKS_NOT_OFFLINE,
                    'error_msg': SERVER_LINKS_NOT_OFFLINE_SETTINGS_MSG,
                }, 400)

        if name_def:
            svr.name = name
        if network_def:
            svr.network = network
        if network_start_def:
            svr.network_start = network_start
        if network_end_def:
            svr.network_end = network_end
        if restrict_routes_def:
            svr.restrict_routes = restrict_routes
        if ipv6_def:
            svr.ipv6 = ipv6
        if ipv6_firewall_def:
            svr.ipv6_firewall = ipv6_firewall
        if network_mode_def:
            if network_mode == BRIDGE and (
                    not network_start or not network_end):
                return utils.jsonify({
                    'error': MISSING_PARAMS,
                    'error_msg': MISSING_PARAMS_MSG,
                }, 400)
            svr.network_mode = network_mode
        if bind_address_def:
            svr.bind_address = bind_address
        if port_def:
            svr.port = port
        if protocol_def:
            svr.protocol = protocol
        if dh_param_bits_def and svr.dh_param_bits != dh_param_bits:
            svr.dh_param_bits = dh_param_bits
            svr.generate_dh_param()
        if multi_device_def:
            svr.multi_device = multi_device
        if dns_servers_def:
            svr.dns_servers = dns_servers
        if search_domain_def:
            svr.search_domain = search_domain
        if otp_auth_def:
            svr.otp_auth = otp_auth
        if cipher_def:
            svr.cipher = cipher
        if hash_def:
            svr.hash = hash
        if jumbo_frames_def:
            svr.jumbo_frames = jumbo_frames
        if lzo_compression_def:
            svr.lzo_compression = lzo_compression
        if inter_client_def:
            svr.inter_client = inter_client
        if ping_interval_def:
            svr.ping_interval = ping_interval
        if ping_timeout_def:
            svr.ping_timeout = ping_timeout
        if link_ping_interval_def:
            svr.link_ping_interval = link_ping_interval
        if link_ping_timeout_def:
            svr.link_ping_timeout = link_ping_timeout
        if onc_hostname_def:
            svr.onc_hostname = onc_hostname
        if max_clients_def:
            svr.max_clients = max_clients
        if replica_count_def:
            svr.replica_count = replica_count
        if dns_mapping_def:
            svr.dns_mapping = dns_mapping
        if debug_def:
            svr.debug = debug

        if svr.network_mode == BRIDGE:
            if not _check_network_range(svr.network, svr.network_start,
                    svr.network_end):
                return utils.jsonify({
                    'error': BRIDGE_NETWORK_INVALID,
                    'error_msg': BRIDGE_NETWORK_INVALID_MSG,
                }, 400)

            if svr.ipv6:
                return utils.jsonify({
                    'error': IPV6_BRIDGED_INVALID,
                    'error_msg': IPV6_BRIDGED_INVALID_MSG,
                }, 400)

        if svr.links and svr.replica_count > 1:
            return utils.jsonify({
                'error': SERVER_LINKS_AND_REPLICA,
                'error_msg': SERVER_LINKS_AND_REPLICA_MSG,
            }, 400)

        svr.commit(svr.changed)

    logger.LogEntry(message='Created server "%s".' % svr.name)
    event.Event(type=SERVERS_UPDATED)
    event.Event(type=SERVER_ROUTES_UPDATED, resource_id=svr.id)
    for org in svr.iter_orgs():
        event.Event(type=USERS_UPDATED, resource_id=org.id)
    return utils.jsonify(svr.dict())
Beispiel #26
0
def main(default_conf=None):
    if len(sys.argv) > 1:
        cmd = sys.argv[1]
    else:
        cmd = 'start'

    parser = optparse.OptionParser(usage=USAGE)

    if cmd == 'start':
        parser.add_option('-d',
                          '--daemon',
                          action='store_true',
                          help='Daemonize process')
        parser.add_option('-p',
                          '--pidfile',
                          type='string',
                          help='Path to create pid file')
        parser.add_option('-c',
                          '--conf',
                          type='string',
                          help='Path to configuration file')
        parser.add_option('-q',
                          '--quiet',
                          action='store_true',
                          help='Suppress logging output')
    elif cmd == 'logs':
        parser.add_option('--archive',
                          action='store_true',
                          help='Archive log file')
        parser.add_option('--tail', action='store_true', help='Tail log file')
        parser.add_option('--limit', type='int', help='Limit log lines')
        parser.add_option('--natural',
                          action='store_true',
                          help='Natural log sort')
    elif cmd == 'set':
        parser.disable_interspersed_args()

    (options, args) = parser.parse_args()

    if hasattr(options, 'conf') and options.conf:
        conf_path = options.conf
    else:
        conf_path = default_conf
    pritunl.set_conf_path(conf_path)

    if cmd == 'version':
        print('%s v%s' % (pritunl.__title__, pritunl.__version__))
        sys.exit(0)
    elif cmd == 'setup-key':
        from pritunl import setup
        from pritunl import settings

        setup.setup_loc()
        print(settings.local.setup_key)

        sys.exit(0)
    elif cmd == 'reset-version':
        from pritunl.constants import MIN_DATABASE_VER
        from pritunl import setup
        from pritunl import utils

        setup.setup_db()
        utils.set_db_ver(pritunl.__version__, MIN_DATABASE_VER)

        time.sleep(.2)
        print('Database version reset to %s' % pritunl.__version__)

        sys.exit(0)
    elif cmd == 'reset-password':
        from pritunl import setup
        from pritunl import auth

        setup.setup_db()
        username, password = auth.reset_password()

        print('Administrator password successfully reset:\n' + \
            '  username: "******"\n  password: "******"' % (username, password))

        sys.exit(0)
    elif cmd == 'default-password':
        from pritunl import setup
        from pritunl import auth

        setup.setup_db()
        username, password = auth.get_default_password()

        if not password:
            print('No default password available, use reset-password')
        else:
            print('Administrator default password:\n' + \
                '  username: "******"\n  password: "******"' % (username, password))

        sys.exit(0)
    elif cmd == 'reconfigure':
        from pritunl import setup
        from pritunl import settings
        setup.setup_loc()

        settings.conf.mongodb_uri = None
        settings.conf.commit()

        time.sleep(.2)
        print('Database configuration successfully reset')

        sys.exit(0)
    elif cmd == 'get':
        from pritunl import setup
        from pritunl import settings
        setup.setup_db_host()

        if len(args) != 2:
            raise ValueError('Invalid arguments')

        split = args[1].split('.')
        key_str = None
        group_str = split[0]
        if len(split) > 1:
            key_str = split[1]

        if group_str == 'host':
            group = settings.local.host
        else:
            group = getattr(settings, group_str)

        if key_str:
            val = getattr(group, key_str)
            print('%s.%s = %s' % (group_str, key_str,
                                  json.dumps(val, default=lambda x: str(x))))

        else:
            for field in group.fields:
                val = getattr(group, field)
                print('%s.%s = %s' %
                      (group_str, field,
                       json.dumps(val, default=lambda x: str(x))))

        sys.exit(0)
    elif cmd == 'set':
        from pritunl.constants import HOSTS_UPDATED
        from pritunl import setup
        from pritunl import settings
        from pritunl import event
        from pritunl import messenger
        setup.setup_db_host()

        if len(args) != 3:
            raise ValueError('Invalid arguments')

        group_str, key_str = args[1].split('.')

        if group_str == 'host':
            group = settings.local.host
        else:
            group = getattr(settings, group_str)

        val_str = args[2]
        try:
            val = json.loads(val_str)
        except ValueError:
            val = json.loads(json.JSONEncoder().encode(val_str))

        setattr(group, key_str, val)

        if group_str == 'host':
            settings.local.host.commit()

            event.Event(type=HOSTS_UPDATED)
            messenger.publish('hosts', 'updated')
        else:
            settings.commit()

        time.sleep(.2)

        print('%s.%s = %s' %
              (group_str, key_str,
               json.dumps(getattr(group, key_str), default=lambda x: str(x))))
        print('Successfully updated configuration. This change is ' \
            'stored in the database and has been applied to all hosts ' \
            'in the cluster.')

        sys.exit(0)
    elif cmd == 'unset':
        from pritunl import setup
        from pritunl import settings
        setup.setup_db()

        if len(args) != 2:
            raise ValueError('Invalid arguments')

        group_str, key_str = args[1].split('.')

        group = getattr(settings, group_str)

        group.unset(key_str)

        settings.commit()

        time.sleep(.2)

        print('%s.%s = %s' %
              (group_str, key_str,
               json.dumps(getattr(group, key_str), default=lambda x: str(x))))
        print('Successfully updated configuration. This change is ' \
            'stored in the database and has been applied to all hosts ' \
            'in the cluster.')

        sys.exit(0)
    elif cmd == 'set-mongodb':
        from pritunl import setup
        from pritunl import settings
        setup.setup_loc()

        if len(args) > 1:
            mongodb_uri = args[1]
        else:
            mongodb_uri = None

        settings.conf.mongodb_uri = mongodb_uri
        settings.conf.commit()

        time.sleep(.2)
        print('Database configuration successfully set')

        sys.exit(0)
    elif cmd == 'reset-ssl-cert':
        from pritunl import setup
        from pritunl import settings
        setup.setup_db()

        settings.app.server_cert = None
        settings.app.server_key = None
        settings.app.acme_timestamp = None
        settings.app.acme_key = None
        settings.app.acme_domain = None
        settings.commit()

        time.sleep(.2)
        print('Server ssl certificate successfully reset')

        sys.exit(0)
    elif cmd == 'destroy-secondary':
        from pritunl import setup
        from pritunl import logger
        from pritunl import mongo

        setup.setup_db()

        print('Destroying secondary database...')

        mongo.get_collection('clients').drop()
        mongo.get_collection('clients_pool').drop()
        mongo.get_collection('transaction').drop()
        mongo.get_collection('queue').drop()
        mongo.get_collection('tasks').drop()

        mongo.get_collection('messages').drop()
        mongo.get_collection('users_key_link').drop()
        mongo.get_collection('auth_sessions').drop()
        mongo.get_collection('auth_csrf_tokens').drop()
        mongo.get_collection('auth_limiter').drop()
        mongo.get_collection('otp').drop()
        mongo.get_collection('otp_cache').drop()
        mongo.get_collection('sso_tokens').drop()
        mongo.get_collection('sso_push_cache').drop()
        mongo.get_collection('sso_client_cache').drop()
        mongo.get_collection('sso_passcode_cache').drop()

        setup.upsert_indexes()

        server_coll = mongo.get_collection('servers')
        server_coll.update_many({}, {
            '$set': {
                'status': 'offline',
                'instances': [],
                'instances_count': 0,
            },
            '$unset': {
                'network_lock': '',
                'network_lock_ttl': '',
            },
        })

        print('Secondary database destroyed')

        sys.exit(0)
    elif cmd == 'repair-database':
        from pritunl import setup
        from pritunl import logger
        from pritunl import mongo

        setup.setup_db()

        print('Repairing database...')

        mongo.get_collection('clients').drop()
        mongo.get_collection('clients_pool').drop()
        mongo.get_collection('transaction').drop()
        mongo.get_collection('queue').drop()
        mongo.get_collection('tasks').drop()

        mongo.get_collection('messages').drop()
        mongo.get_collection('users_key_link').drop()
        mongo.get_collection('auth_sessions').drop()
        mongo.get_collection('auth_csrf_tokens').drop()
        mongo.get_collection('auth_limiter').drop()
        mongo.get_collection('otp').drop()
        mongo.get_collection('otp_cache').drop()
        mongo.get_collection('sso_tokens').drop()
        mongo.get_collection('sso_push_cache').drop()
        mongo.get_collection('sso_client_cache').drop()
        mongo.get_collection('sso_passcode_cache').drop()

        mongo.get_collection('logs').drop()
        mongo.get_collection('log_entries').drop()
        mongo.get_collection('servers_ip_pool').drop()

        setup.upsert_indexes()

        server_coll = mongo.get_collection('servers')
        server_coll.update_many({}, {
            '$set': {
                'status': 'offline',
                'instances': [],
                'instances_count': 0,
            },
            '$unset': {
                'network_lock': '',
                'network_lock_ttl': '',
            },
        })

        from pritunl import server

        for svr in server.iter_servers():
            try:
                svr.ip_pool.sync_ip_pool()
            except:
                logger.exception(
                    'Failed to sync server IP pool',
                    'tasks',
                    server_id=svr.id,
                )

        server_coll.update_many({}, {
            '$set': {
                'status': 'offline',
                'instances': [],
                'instances_count': 0,
            },
            '$unset': {
                'network_lock': '',
                'network_lock_ttl': '',
            },
        })

        print('Database repair complete')

        sys.exit(0)
    elif cmd == 'logs':
        from pritunl import setup
        from pritunl import logger
        setup.setup_db()

        log_view = logger.LogView()

        if options.archive:
            if len(args) > 1:
                archive_path = args[1]
            else:
                archive_path = './'
            print('Log archived to: ' + log_view.archive_log(
                archive_path, options.natural, options.limit))
        elif options.tail:
            for msg in log_view.tail_log_lines():
                print(msg)
        else:
            print(
                log_view.get_log_lines(
                    natural=options.natural,
                    limit=options.limit,
                ))

        sys.exit(0)
    elif cmd == 'clear-auth-limit':
        from pritunl import setup
        from pritunl import logger
        from pritunl import mongo
        from pritunl import settings

        setup.setup_db()

        mongo.get_collection('auth_limiter').delete_many({})

        print('Auth limiter cleared')

        sys.exit(0)
    elif cmd == 'clear-logs':
        from pritunl import setup
        from pritunl import logger
        from pritunl import mongo
        from pritunl import settings

        setup.setup_db()

        mongo.get_collection('logs').drop()
        mongo.get_collection('log_entries').drop()

        prefix = settings.conf.mongodb_collection_prefix or ''

        log_limit = settings.app.log_limit
        mongo.database.create_collection(prefix + 'logs',
                                         capped=True,
                                         size=log_limit * 1024,
                                         max=log_limit)

        log_entry_limit = settings.app.log_entry_limit
        mongo.database.create_collection(prefix + 'log_entries',
                                         capped=True,
                                         size=log_entry_limit * 512,
                                         max=log_entry_limit)

        print('Log entries cleared')

        sys.exit(0)
    elif cmd != 'start':
        raise ValueError('Invalid command')

    from pritunl import settings

    if options.quiet:
        settings.local.quiet = True

    if options.daemon:
        pid = os.fork()
        if pid > 0:
            if options.pidfile:
                with open(options.pidfile, 'w') as pid_file:
                    pid_file.write('%s' % pid)
            sys.exit(0)
    elif not options.quiet:
        print('##############################################################')
        print('#                                                            #')
        print('#                      /$$   /$$                         /$$ #')
        print('#                     |__/  | $$                        | $$ #')
        print('#   /$$$$$$   /$$$$$$  /$$ /$$$$$$   /$$   /$$ /$$$$$$$ | $$ #')
        print('#  /$$__  $$ /$$__  $$| $$|_  $$_/  | $$  | $$| $$__  $$| $$ #')
        print('# | $$  \ $$| $$  \__/| $$  | $$    | $$  | $$| $$  \ $$| $$ #')
        print('# | $$  | $$| $$      | $$  | $$ /$$| $$  | $$| $$  | $$| $$ #')
        print('# | $$$$$$$/| $$      | $$  |  $$$$/|  $$$$$$/| $$  | $$| $$ #')
        print('# | $$____/ |__/      |__/   \____/  \______/ |__/  |__/|__/ #')
        print('# | $$                                                       #')
        print('# | $$                                                       #')
        print('# |__/                                                       #')
        print('#                                                            #')
        print('##############################################################')

    pritunl.init_server()
Beispiel #27
0
def sso_callback_get():
    sso_mode = settings.app.sso

    if sso_mode not in (GOOGLE_AUTH, GOOGLE_DUO_AUTH, SLACK_AUTH,
            SLACK_DUO_AUTH, SAML_AUTH, SAML_DUO_AUTH, SAML_OKTA_AUTH,
            SAML_OKTA_DUO_AUTH, SAML_ONELOGIN_AUTH, SAML_ONELOGIN_DUO_AUTH):
        return flask.abort(405)

    state = flask.request.args.get('state')
    sig = flask.request.args.get('sig')

    tokens_collection = mongo.get_collection('sso_tokens')
    doc = tokens_collection.find_and_modify(query={
        '_id': state,
    }, remove=True)

    if not doc:
        return flask.abort(404)

    query = flask.request.query_string.split('&sig=')[0]
    test_sig = base64.urlsafe_b64encode(hmac.new(str(doc['secret']),
        query, hashlib.sha512).digest())

    if sig != test_sig:
        return flask.abort(401)

    params = urlparse.parse_qs(query)

    if doc.get('type') == SAML_AUTH:
        username = params.get('username')[0]
        email = params.get('email', [None])[0]
        org_name = params.get('org', [None])[0]

        if not username:
            return flask.abort(406)

        valid, org_name = sso.verify_saml(username, email, org_name)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org
        if org_name:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id
    elif doc.get('type') == SLACK_AUTH:
        username = params.get('username')[0]
        email = None
        user_team = params.get('team')[0]
        org_names = params.get('orgs', [''])[0]
        org_names = org_names.split(',')

        valid, org_name = sso.verify_slack(username, user_team, org_names)
        if not valid:
            return flask.abort(401)

        if org_name:
            org_names = [org_name]

        org_id = settings.app.sso_org
        for org_name in org_names:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id
                break
    else:
        username = params.get('username')[0]
        email = username

        valid, org_name = sso.verify_google(username)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org
        if org_name:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id
    if DUO_AUTH in sso_mode:
        valid, _ = sso.auth_duo(
            username,
            ipaddr=flask.request.remote_addr,
            type='Key',
        )
        if not valid:
            return flask.abort(401)

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(405)

    usr = org.find_user(name=username)
    if not usr:
        usr = org.new_user(name=username, email=email, type=CERT_CLIENT,
            auth_type=sso_mode)
        usr.audit_event('user_created', 'User created with single sign-on',
            remote_addr=utils.get_remote_addr())

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if usr.disabled:
            return flask.abort(403)

        if usr.auth_type != sso_mode:
            usr.auth_type = sso_mode
            usr.commit('auth_type')

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event('user_profile',
        'User profile viewed from single sign-on',
        remote_addr=utils.get_remote_addr(),
    )

    return utils.redirect(utils.get_url_root()[:-1] + key_link['view_url'])
Beispiel #28
0
def sso_authenticate_post():
    if settings.app.sso != DUO_AUTH:
        return flask.abort(405)

    username = flask.request.json['username']
    usernames = [username]
    email = None
    if '@' in username:
        email = username
        usernames.append(username.split('@')[0])

    valid = False
    for i, username in enumerate(usernames):
        try:
            valid, org_id = sso.auth_duo(
                username,
                strong=True,
                ipaddr=flask.request.remote_addr,
                type='Key',
            )
            break
        except InvalidUser:
            if i == len(usernames) - 1:
                logger.error('Invalid duo username', 'sso',
                    username=username,
                )

    if not valid:
        logger.error('Invalid duo username', 'sso',
            username=username,
        )
        return flask.abort(401)

    if not org_id:
        org_id = settings.app.sso_org

    org = organization.get_by_id(org_id)
    if not org:
        logger.error('Organization for Duo sso does not exist', 'sso',
            org_id=org_id,
        )
        return flask.abort(405)

    usr = org.find_user(name=username)
    if not usr:
        usr = org.new_user(name=username, email=email, type=CERT_CLIENT,
            auth_type=DUO_AUTH)
        usr.audit_event('user_created', 'User created with single sign-on',
            remote_addr=utils.get_remote_addr())

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if usr.disabled:
            return flask.abort(403)

        if usr.auth_type != DUO_AUTH:
            usr.auth_type = DUO_AUTH
            usr.commit('auth_type')
            event.Event(type=USERS_UPDATED, resource_id=org.id)

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event('user_profile',
        'User profile viewed from single sign-on',
        remote_addr=utils.get_remote_addr(),
    )

    return utils.get_url_root()[:-1] + key_link['view_url']
Beispiel #29
0
def user_key_pin_put(key_id):
    if settings.app.demo_mode:
        return utils.demo_blocked()

    doc = _find_doc({
        'key_id': key_id,
    })
    if not doc:
        return flask.abort(404)

    if settings.app.demo_mode:
        return utils.demo_blocked()

    if settings.user.pin_mode == PIN_DISABLED:
        return utils.jsonify({
            'error': PIN_IS_DISABLED,
            'error_msg': PIN_IS_DISABLED_MSG,
        }, 400)

    org = organization.get_by_id(doc['org_id'])
    usr = org.get_user(doc['user_id'])
    if usr.disabled:
        return flask.abort(403)

    if RADIUS_AUTH in usr.auth_type:
        return utils.jsonify({
            'error': PIN_RADIUS,
            'error_msg': PIN_RADIUS_MSG,
        }, 400)

    current_pin = utils.filter_str(
        flask.request.json.get('current_pin')) or None
    pin = utils.filter_str(flask.request.json.get('pin')) or None

    if pin:
        if not pin.isdigit():
            return utils.jsonify({
                'error': PIN_NOT_DIGITS,
                'error_msg': PIN_NOT_DIGITS_MSG,
            }, 400)

        if len(pin) < settings.user.pin_min_length:
            return utils.jsonify({
                'error': PIN_TOO_SHORT,
                'error_msg': PIN_TOO_SHORT_MSG,
            }, 400)

    if usr.pin and not usr.check_pin(current_pin):
        return utils.jsonify({
            'error': PIN_INVALID,
            'error_msg': PIN_INVALID_MSG,
        }, 400)

    if usr.set_pin(pin):
        usr.audit_event('user_updated',
            'User pin changed with temporary profile link',
            remote_addr=utils.get_remote_addr(),
        )

    usr.commit()

    event.Event(type=USERS_UPDATED, resource_id=org.id)

    return utils.jsonify({})
Beispiel #30
0
def org_post():
    name = utils.filter_str(flask.request.json['name'])
    org = organization.new_org(name=name, type=ORG_DEFAULT)
    logger.LogEntry(message='Created new organization "%s".' % org.name)
    event.Event(type=ORGS_UPDATED)
    return utils.jsonify(org.dict())