def __init__(self, ctx, form, data):
     self.ctx = ctx
     self.form = form
     self.data = data
     self.toplevel_fda = formalutils.FormDataAccessor(form, [], ctx)
     self.client_connection_fda = formalutils.FormDataAccessor(
         form, ['client_connection'], ctx)
Ejemplo n.º 2
0
    def fill_users_group(self, ctx, form, g):
        fda = formalutils.FormDataAccessor(form, ['userlist_group'], ctx)

        ui_root = helpers.get_ui_config()
        if ui_root.hasS(ns_ui.users):
            for idx, user in enumerate(
                    ui_root.getS(ns_ui.users, rdf.Seq(rdf.Type(ns_ui.User)))):
                try:
                    g = self._create_user_list_entry(idx)

                    fda_user = fda.descend(str(idx))
                    fda_user['username'] = user.getS(ns_ui.username,
                                                     rdf.String)
                    #fda_user['password'] = user.getS(ns_ui.password, rdf.String)
                    fda_user['password'] = ''
                    if user.hasS(ns_ui.fixedIp):
                        fda_user['fixed_ip'] = user.getS(
                            ns_ui.fixedIp, rdf.IPv4Address)
                    else:
                        fda_user['fixed_ip'] = None
                    fda_user['admin_rights'] = user.getS(
                        ns_ui.adminRights, rdf.Boolean)
                    fda_user['vpn_rights'] = user.getS(ns_ui.vpnRights,
                                                       rdf.Boolean)
                except:
                    _log.exception('cannot fill data for a user, skipping')
Ejemplo n.º 3
0
    def save_client_connection_data(self, ctx, form, data):
        cc_fda = formalutils.FormDataAccessor(form, ['client_connection'], ctx)
        ui_root = helpers.get_new_ui_config()

        # Server address & psk
        if cc_fda.has_key('server_name') and cc_fda['server_name'] is not None:
            ui_root.setS(ns_ui.vpnServerAddress, rdf.String,
                         cc_fda['server_name'])
        else:
            ui_root.setS(ns_ui.vpnServerAddress, rdf.String, '')
        psk_seq = ui_root.setS(ns_ui.preSharedKeys,
                               rdf.Seq(rdf.Type(ns_ui.PreSharedKey)))
        if cc_fda.has_key('psk_1') and (cc_fda['psk_1'] !=
                                        '') and (cc_fda['psk_1'] is not None):
            psk = psk_seq.new()
            psk.setS(ns_ui.preSharedKey, rdf.String, cc_fda['psk_1'])
        if cc_fda.has_key('psk_2') and (cc_fda['psk_2'] !=
                                        '') and (cc_fda['psk_2'] is not None):
            psk = psk_seq.new()
            psk.setS(ns_ui.preSharedKey, rdf.String, cc_fda['psk_2'])
        # DNS
        if cc_fda['dns'] == 'use_ic_dns':
            ui_root.setS(ns_ui.clientDnsServers,
                         rdf.Type(ns_ui.NetworkConnectionDns))
        elif cc_fda['dns'] == 'manual_dns':
            dns_root = ui_root.setS(ns_ui.clientDnsServers,
                                    rdf.Type(ns_ui.SetDnsServers))
            uidatahelpers.save_optional_field_to_rdf(dns_root,
                                                     ns_ui.primaryDns,
                                                     rdf.IPv4Address, cc_fda,
                                                     'dns_1')
            uidatahelpers.save_optional_field_to_rdf(dns_root,
                                                     ns_ui.secondaryDns,
                                                     rdf.IPv4Address, cc_fda,
                                                     'dns_2')
        else:
            raise uidatahelpers.FormDataError(
                'Client connection dns is neither network dns nor set dns.')
        # WINS
        # Note: parent node is ui-root, which may already have a value from old config, use empty default
        # value to remove old data in case form value is missing.
        uidatahelpers.save_optional_field_to_rdf(ui_root,
                                                 ns_ui.clientPrimaryWins,
                                                 rdf.IPv4Address,
                                                 cc_fda,
                                                 'wins_1',
                                                 default=None)
        uidatahelpers.save_optional_field_to_rdf(ui_root,
                                                 ns_ui.clientSecondaryWins,
                                                 rdf.IPv4Address,
                                                 cc_fda,
                                                 'wins_2',
                                                 default=None)
        ui_root.setS(ns_ui.clientSubnet, rdf.IPv4Subnet,
                     cc_fda['client_subnet'])
        ui_root.setS(ns_ui.clientAddressRange, rdf.IPv4AddressRange,
                     cc_fda['client_address_range'])

        ui_root.setS(ns_ui.clientCompression, rdf.Boolean,
                     cc_fda['client_compression'])
    def _clear_errors_from_disabled_fields(self):
        """Clears all the field errors from disabled fields.

        Validation must know which fields are disabled, while all the fields are enabled in the form post.
        """
        form_fda = formalutils.FormDataAccessor(self.form, [], self.ctx)
        self._walk_through_disabled_fields(
            form_fda.clear_local_errors_and_warnings)
    def _is_disabled(self, fda, fda_key, full_key=None):
        """Returns true if the field is disabled."""
        if full_key is None:
            search_key = fda.combine(fda_key)
        else:
            search_key = full_key

        # Check if the field is in the dis_fields list.
        if self.dis_fields.has_key(search_key):
            # Check the conditions.
            # Uses full key names and main fda in order to give a possibility to disable/enable elements from
            # other groups.
            form_fda = formalutils.FormDataAccessor(self.form, [], self.ctx)
            for k in self.dis_fields[search_key].keys():
                # If k is not found in main fda, k has a local error. Only local error in selection is that
                # selection is missing -> not disabled. Continue with other possible selections.
                if not (form_fda.has_key(k)):
                    continue
                if form_fda[k] != self.dis_fields[search_key][k]:
                    return True
        else:
            # Check if the key matches to dynamic list entries.
            for key in self.dyn_list_dis_fields.keys():
                dyn_list_name, dyn_list_field = key.split('*')
                if (search_key[:len(dyn_list_name)] == dyn_list_name) and (
                        search_key[-len(dyn_list_field):] == dyn_list_field):
                    # search_key matches, take the list index and check the conditions
                    dyn_list_index = search_key[len(dyn_list_name
                                                    ):-len(dyn_list_field)]

                    for cond_key in self.dyn_list_dis_fields[key].keys():
                        cond_field = dyn_list_name + dyn_list_index + cond_key.split(
                            '*')[1]
                        form_fda = formalutils.FormDataAccessor(
                            self.form, [], self.ctx)

                        if not (form_fda.has_key(cond_field)):
                            continue

                        if form_fda[cond_field] != self.dyn_list_dis_fields[
                                key][cond_key]:
                            return True

        return False
Ejemplo n.º 6
0
    def form_config(self, ctx):
        form = formal.Form()

        dr = self.create_default_route_group(form, ctx)
        ar = self.create_additional_routes_group(form, ctx)
        sr = self.create_source_routing_group(form, ctx)
        fw = self.create_firewall_group(form, ctx)
        fwrule = self.create_ppp_firewall_group(form, ctx)
        pf = self.create_port_forwarding_group(form, ctx)

        form.add(dr)
        form.add(ar)
        form.add(sr)
        form.add(fwrule)
        form.add(fw)
        form.add(pf)

        try:
            toplevel_fda = formalutils.FormDataAccessor(form, [], ctx)
            self.fill_routing_group(form, ctx, toplevel_fda)
        except:
            _log.exception('failed to fill in form data, ignoring')

        try:
            fw_fda = formalutils.FormDataAccessor(form, ['firewall'], ctx)
            self.fill_firewall_group(form, ctx, fw_fda)
        except:
            _log.exception('failed to fill in form data, ignoring')

        try:
            pf_fda = formalutils.FormDataAccessor(form, ['port_forwards'], ctx)
            self.fill_port_forwarding_group(form, ctx, pf_fda)
        except:
            _log.exception('failed to fill in form data, ignoring')

        sg = formalutils.SubmitFieldGroup('buttons')
        sg.add(
            formalutils.SubmitField('submit',
                                    formal.String(),
                                    label='Save changes'))
        form.add(sg)
        form.addAction(self.submitted, name='submit', validate=False)
        return form
Ejemplo n.º 7
0
    def submitted_configimport(self, ctx, form, data):
        fda = formalutils.FormDataAccessor(form, [], ctx)

        f = None

        # Here is the web UI import logic.  We basically check the ZIP file,
        # extract the RDF/XML data, and stash it to the file system.  We
        # then reboot, handling the actual import during reboot.  To make
        # the use case as good as possible, basic sanity checking of the
        # RDF/XML data is done here, too.
        try:
            fda = fda.descend('import')
            cfg_data = self._parse_configuration_import(fda)
            if cfg_data is None:
                fda.add_error('importfile', 'File missing or empty')
            else:
                _log.info('configuration import file (rdf) is %s bytes long' %
                          len(cfg_data))

                # sanity check
                tmp_model = rdf.Model.fromString(cfg_data)
                if tmp_model is None:
                    raise Exception('cannot create model')

                @db.transact(database=tmp_model)
                def _f():
                    # XXX: more checks here, like version, etc.

                    # write to a temporary file for next reboot
                    f = None
                    try:
                        f = open(constants.CONFIGURATION_IMPORT_BOOT_FILE,
                                 'wb')
                        f.write(tmp_model.toString(name='rdfxml'))
                    finally:
                        if f is not None:
                            f.close()
                            f = None

                _f()

                # reboot host, skip update on next boot
                request = inevow.IRequest(ctx)
                request.redirect(
                    request.URLPath().sibling('waitconfigimport.html'))
                request.finish()
                return ''
        except:
            fda.add_error('importfile', 'Cannot parse file')
            _log.exception('import file check failed')

        if f is not None:
            f.close()

        fda.finalize_validation()
Ejemplo n.º 8
0
    def _validate_radius(self, ctx, form, data):
        fda = formalutils.FormDataAccessor(form, ['radius'], ctx)
        ui_root = helpers.get_ui_config()

        # Basic RADIUS validation - currently limit server addresses to IP addresses
        # because of FreeRADIUS DNS lookup issues (lookup happens during startup and
        # failed lookup makes daemon exit)
        server_ip_addrs = []
        for srv, prt, sec in [('server1', 'serverport1', 'secret1'),
                              ('server2', 'serverport2', 'secret2')]:
            has_ip = False
            if fda.has_key(srv) and fda[srv] is not None and fda[srv] != '':
                # must be IP if nonempty
                has_ip = True
                ip_ok = False
                try:
                    tmp = datatypes.IPv4Address.fromString(fda[srv])
                    server_ip_addrs.append(tmp)
                    ip_ok = True
                except:
                    _log.exception(
                        'cannot parse IP address from user input: %s' %
                        fda[srv])
                if not ip_ok:
                    fda.add_error(srv, 'Invalid IP address')

            if fda.has_key(prt) and fda[prt] is not None:
                pass  # already integer and range validated
            else:
                if has_ip:
                    fda.add_error(
                        prt,
                        'Required when server defined (suggested value: 1812)')

            if fda.has_key(sec) and fda[sec] is not None:
                if not uihelpers.check_radius_secret_characters(fda[sec]):
                    fda.add_error(sec, 'Invalid characters')
            else:
                if has_ip:
                    fda.add_error(sec, 'Required when server defined')

        # If two servers, don't allow same IP for both
        if len(server_ip_addrs) == 2:
            if server_ip_addrs[0] == server_ip_addrs[1]:
                fda.add_error(
                    'server2',
                    'Secondary server address cannot be the same as primary server address'
                )

        # Nas-Identifier validation
        if fda.has_key('nasidentifier') and fda['nasidentifier'] is not None:
            if not uihelpers.check_radius_nai_identifier_characters(
                    fda['nasidentifier']):
                fda.add_error('nasidentifier', 'Invalid characters')
Ejemplo n.º 9
0
    def submitted_start_install(self, ctx, form, data):
        print 'submitted_start_install'

        fda = formalutils.FormDataAccessor(form, [], ctx)
        if not fda['startinstall.acceptlicense']:
            fda.add_error('startinstall.acceptlicense', 'Required')
        fda.finalize_validation()

        request = inevow.IRequest(ctx)
        request.redirect(request.URLPath().sibling('installtarget.html'))
        request.finish()
        return ''
Ejemplo n.º 10
0
    def form_config(self, ctx):
        form = formal.Form()

        ifcount = self.create_iface_count_group(form, ctx)
        pubif = self.create_internet_connection_group(form, ctx)
        privif = self.create_private_network_group(form, ctx)
        dns = self.create_dns_group(form, ctx)
        dyndns = self.create_dynamic_dns_group(form, ctx)
        client = self.create_client_connection_group(form, ctx)

        form.add(ifcount)
        form.add(pubif)
        form.add(privif)
        form.add(dns)
        form.add(dyndns)
        form.add(client)

        try:
            # XXX: this data filler is one unit because ifcount, pubif, privif, dns, and dyndns
            # were previously part of one group
            fda = formalutils.FormDataAccessor(form, [], ctx)
            self.fill_network_config(form, ctx, fda)
        except:
            _log.exception('failed to fill in form data, ignoring')

        try:
            cc_fda = formalutils.FormDataAccessor(form, ['client_connection'],
                                                  ctx)
            self.fill_client_connection_group(form, ctx, cc_fda)
        except:
            _log.exception('failed to fill in form data, ignoring')

        sg = formalutils.SubmitFieldGroup('buttons')
        sg.add(
            formalutils.SubmitField('submit',
                                    formal.String(),
                                    label='Save changes'))
        form.add(sg)
        form.addAction(self.submitted, name='submit', validate=False)
        return form
Ejemplo n.º 11
0
    def fill_radius_group(self, ctx, form, g):
        fda = formalutils.FormDataAccessor(form, ['radius'], ctx)
        ui_root = helpers.get_ui_config()

        fda['server1'] = ui_root.getS(ns_ui.radiusPrimaryServer, rdf.String)
        fda['serverport1'] = ui_root.getS(ns_ui.radiusPrimaryServerPort,
                                          rdf.Integer)
        fda['secret1'] = ui_root.getS(ns_ui.radiusPrimarySecret, rdf.String)
        fda['server2'] = ui_root.getS(ns_ui.radiusSecondaryServer, rdf.String)
        fda['serverport2'] = ui_root.getS(ns_ui.radiusSecondaryServerPort,
                                          rdf.Integer)
        fda['secret2'] = ui_root.getS(ns_ui.radiusSecondarySecret, rdf.String)
        fda['nasidentifier'] = ui_root.getS(ns_ui.radiusNasIdentifier,
                                            rdf.String)
Ejemplo n.º 12
0
    def submitted(self, ctx, form, data):
        fda = formalutils.FormDataAccessor(form, [],
                                           ctx).descend('changepassword')
        if fda.has_key('pw2') and fda.has_key('pw3') and (fda['pw2'] !=
                                                          fda['pw3']):
            fda.add_error('pw2', 'Passwords do not match')
            fda.add_error('pw3', 'Passwords do not match')

        # verify old password
        username = self.get_logged_in_username()
        user_rdf = uihelpers.find_user(username)
        if user_rdf is None:
            # presumably RADIUS user
            fda.add_error('pw1', 'Password change not allowed')
        else:
            if fda.has_key('pw1') and (
                    not uihelpers.check_username_and_password(
                        username, fda['pw1'])):
                fda.add_error('pw1', 'Password incorrect')

        # prevent password change if marker exists; this is useful for demo server
        if os.path.exists(constants.NOPWCHANGE_MARKERFILE):
            _log.info('nopwchange marker exists, not changing password')
            fda.add_error('pw1', 'Password change not allowed')

        # finalize validation
        fda.finalize_validation()

        # XXX: does admin need control here? i.e., prevent changing of password?

        # ok, we're happy; change the password
        _log.info('changing password for user %s' % username)
        uihelpers.change_user_password(username, fda['pw2'])

        # restart radius server with new config; no need to nuke connections here because
        # no users are added or removed.
        try:
            pd = uidatahelpers.CreateProtocolData()
            pd.save_protocol_data(use_current_config=True)
            pd.activate_protocol_data(use_current_config=True)
            pd.restart_freeradius()  # needs protocol config in place
        except:
            _log.exception('cannot restart freeradius, ignoring')

        # redirect
        request = inevow.IRequest(ctx)
        request.redirect(request.URLPath().sibling('passwordchanged.html'))
        request.finish()
        return ''
Ejemplo n.º 13
0
    def save_firewall_data(self, ctx, form, data):
        def _save_port_forward_to_rdf(rdf_node, fda):
            rdf_node.setS(ns_ui.protocol, rdf.String, fda['new_fw_protocol'])
            uidatahelpers.save_optional_field_to_rdf(rdf_node,
                                                     ns_ui.incomingPort,
                                                     rdf.Integer, fda,
                                                     'new_fw_port_in')
            rdf_node.setS(ns_ui.ipAddress, rdf.IPv4Address,
                          fda['new_fw_ip_out'])
            uidatahelpers.save_optional_field_to_rdf(rdf_node,
                                                     ns_ui.destinationPort,
                                                     rdf.Integer, fda,
                                                     'new_fw_port_out')

        ui_root = helpers.get_new_ui_config()
        fw_fda = formalutils.FormDataAccessor(form, ['firewall'], ctx)
        ui_root.setS(ns_ui.firewallInUse, rdf.Boolean,
                     fw_fda['firewall_in_use'])

        # XXX: separate function
        pf_fda = formalutils.FormDataAccessor(form, ['port_forwards'], ctx)
        uidatahelpers.save_dynamic_list_to_rdf(ui_root, ns_ui.portForwards,
                                               ns_ui.PortForward, pf_fda,
                                               _save_port_forward_to_rdf)
Ejemplo n.º 14
0
 def create_debug_group(self, form, ctx):
     debug_group = formalutils.CollapsibleGroup('debug_group',
                                                label='Debug')
     debug_group.setCollapsed(False)
     debug_group.add(
         formal.Field('debug',
                      formal.Integer(
                          required=True,
                          validators=[formal.RangeValidator(min=0, max=2)]),
                      label='Debug mode (0=normal, 1=light, 2=heavy)'))
     ui_root = db.get_db().getRoot().getS(ns_ui.uiConfig,
                                          rdf.Type(ns_ui.UiConfig))
     # Default false if no entry found from the database.
     debug_fda = formalutils.FormDataAccessor(form, ['debug_group'], ctx)
     if ui_root.hasS(ns_ui.debug):
         debug_fda['debug'] = ui_root.getS(ns_ui.debug, rdf.Integer)
     else:
         debug_fda['debug'] = 0
     return debug_group
Ejemplo n.º 15
0
    def save_user_list(self, ctx, form, data, userpw_dict):
        def _save_user_to_rdf(user, fda):
            username = fda['username']
            user.setS(ns_ui.username, rdf.String, username)

            # Password is tricky; we look up the previous config, and if a user
            # of this name existed and it had a password, use that password unless
            # a new one is specified.  This is not perfect, but at least it works
            # correctly w.r.t. changed username.  Note however that we do not track
            # user identity as such across a name change: if admin removes user XYZ
            # and adds a new user with name XYZ (with empty password field), that
            # user will simply inherit the older user XYZ password.

            if fda.has_key('password') and (fda['password'] is not None) and (
                    fda['password'] != ''):
                # set hashed password entries
                uihelpers.set_user_password_hashes(user, fda['password'])
            else:
                if userpw_dict.has_key(username):
                    password_plain, password_md5, password_nt = userpw_dict[
                        username]
                    user.setS(ns_ui.passwordMd5, rdf.String, password_md5)
                    user.setS(ns_ui.passwordNtHash, rdf.String, password_nt)
                    user.removeNodes(ns_ui.password)
                else:
                    # this should not happen; log but don't fail badly
                    _log.error(
                        'no password in form or userpw dict, should not happen'
                    )
                    user.setS(ns_ui.password, rdf.String, '')

            uidatahelpers.save_optional_field_to_rdf(user, ns_ui.fixedIp,
                                                     rdf.IPv4Address, fda,
                                                     'fixed_ip')
            user.setS(ns_ui.adminRights, rdf.Boolean, fda['admin_rights'])
            user.setS(ns_ui.vpnRights, rdf.Boolean, fda['vpn_rights'])

        ui_root = helpers.get_new_ui_config()
        fda = formalutils.FormDataAccessor(form, ['userlist_group'], ctx)
        uidatahelpers.save_dynamic_list_to_rdf(ui_root, ns_ui.users,
                                               ns_ui.User, fda,
                                               _save_user_to_rdf)
Ejemplo n.º 16
0
    def _walk_through_disabled_fields(self, func):
        """Iterate trough disabled field keys and call function given as a parameter if a field is disabled."""

        # Dynamic list callback function.
        def _check_dynamic_field(list_item_fda, list_index):
            search_key = dyn_list + str(list_index) + dyn_list_field
            if self._is_disabled(None, None, search_key):
                func(search_key)

        # Non-dynamic fields
        for key in self.dis_fields.keys():
            if self._is_disabled(None, None, key):
                func(key)

        # Dynamic list fields
        for key in self.dyn_list_dis_fields:
            dyn_list, dyn_list_field = key.split('*')
            dyn_list_fda = formalutils.FormDataAccessor(
                self.form, [dyn_list[:-1]],
                self.ctx)  # Take '.' away from dyn_list end.
            self._walk_through_dynamic_list(dyn_list_fda, _check_dynamic_field)
Ejemplo n.º 17
0
    def fill_s2s_list(self, form, ctx, conn_list):
        fda = formalutils.FormDataAccessor(form, ['s2s_connections'], ctx)

        ui_root = helpers.get_ui_config()
        if ui_root.hasS(ns_ui.siteToSiteConnections):
            for idx, conn in enumerate(
                    ui_root.getS(ns_ui.siteToSiteConnections,
                                 rdf.Seq(rdf.Type(
                                     ns_ui.SiteToSiteConnection)))):
                try:
                    g = self._create_s2s_connection_list_entry(idx)

                    fda_conn = fda.descend(str(idx))
                    fda_conn['s2s_username'] = conn.getS(
                        ns_ui.username, rdf.String)
                    fda_conn['s2s_password'] = conn.getS(
                        ns_ui.password, rdf.String)
                    # XXX: why is this API so weird? why not give the rdf:Seq and get a string in response?
                    uidatahelpers.fill_subnet_list_to_form(
                        conn, ns_ui.subnetList, fda_conn, 's2s_subnets')

                    mode = conn.getS(ns_ui.mode, rdf.String)
                    if mode == 'client':
                        fda_conn['s2s_mode'] = 'client'
                        fda_conn['s2s_psk'] = conn.getS(
                            ns_ui.preSharedKey, rdf.String)
                        fda_conn['s2s_server'] = conn.getS(
                            ns_ui.serverAddress, rdf.String)
                    elif mode == 'server':
                        fda_conn['s2s_mode'] = 'server'
                        fda_conn['s2s_psk'] = ''
                        fda_conn['s2s_server'] = ''
                    else:
                        raise 'unknown mode: %s' % mode

                    conn_list.add(g)
                except:
                    _log.exception(
                        'cannot fill data for s2s connection, skipping')
Ejemplo n.º 18
0
    def save_s2s_list_data(self, ctx, form, data):
        def _save_connection(conn, fda):
            conn.setS(ns_ui.username, rdf.String, fda['s2s_username'])
            conn.setS(ns_ui.password, rdf.String, fda['s2s_password'])
            uidatahelpers.save_subnet_list_to_rdf(conn, ns_ui.subnetList, fda,
                                                  's2s_subnets')
            mode = fda['s2s_mode']
            if mode == 'client':
                conn.setS(ns_ui.mode, rdf.String, 'client')
                conn.setS(ns_ui.preSharedKey, rdf.String, fda['s2s_psk'])
                conn.setS(ns_ui.serverAddress, rdf.String, fda['s2s_server'])
            elif mode == 'server':
                conn.setS(ns_ui.mode, rdf.String, 'server')
            else:
                raise Exception('unknown mode: %s' % mode)

        ui_root = helpers.get_new_ui_config()
        fda = formalutils.FormDataAccessor(form, ['s2s_connections'], ctx)
        uidatahelpers.save_dynamic_list_to_rdf(ui_root,
                                               ns_ui.siteToSiteConnections,
                                               ns_ui.SiteToSiteConnection, fda,
                                               _save_connection)
Ejemplo n.º 19
0
    def save_radius(self, ctx, form, data):
        ui_root = helpers.get_new_ui_config()
        fda = formalutils.FormDataAccessor(form, ['radius'], ctx)

        val = ''
        if fda.has_key('server1') and fda['server1'] is not None:
            val = fda['server1']
        ui_root.setS(ns_ui.radiusPrimaryServer, rdf.String, val)

        val = 1812
        if fda.has_key('serverport1') and fda['serverport1'] is not None:
            val = fda['serverport1']
        ui_root.setS(ns_ui.radiusPrimaryServerPort, rdf.Integer, val)

        val = ''
        if fda.has_key('secret1') and fda['secret1'] is not None:
            val = fda['secret1']
        ui_root.setS(ns_ui.radiusPrimarySecret, rdf.String, val)

        val = ''
        if fda.has_key('server2') and fda['server2'] is not None:
            val = fda['server2']
        ui_root.setS(ns_ui.radiusSecondaryServer, rdf.String, val)

        val = 1812
        if fda.has_key('serverport2') and fda['serverport2'] is not None:
            val = fda['serverport2']
        ui_root.setS(ns_ui.radiusSecondaryServerPort, rdf.Integer, val)

        val = ''
        if fda.has_key('secret2') and fda['secret2'] is not None:
            val = fda['secret2']
        ui_root.setS(ns_ui.radiusSecondarySecret, rdf.String, val)

        val = ''
        if fda.has_key('nasidentifier') and fda['nasidentifier'] is not None:
            val = fda['nasidentifier']
        ui_root.setS(ns_ui.radiusNasIdentifier, rdf.String, val)
Ejemplo n.º 20
0
 def submitted(self, ctx, form, data):
     fda = formalutils.FormDataAccessor(form, [], ctx)
     fda.finalize_validation()
     self.save_ui_data(ctx, form, data)
Ejemplo n.º 21
0
 def save_debug(self, ctx, form, data):
     ui_root = db.get_db().getRoot().getS(ns_ui.uiConfig,
                                          rdf.Type(ns_ui.UiConfig))
     debug_fda = formalutils.FormDataAccessor(form, ['debug_group'], ctx)
     ui_root.setS(ns_ui.debug, rdf.Integer, debug_fda['debug'])
Ejemplo n.º 22
0
    def submitted(self, ctx, form, data):
        fda = formalutils.FormDataAccessor(form, [], ctx)
        pd = uidatahelpers.CreateProtocolData()

        # Save collapsed states first, so they feed back to next round
        for [rdf_uri,
             key] in [[ns_ui.collapseInterfaceCount, 'ifcount_group'],
                      [ns_ui.collapseInternetConnection, 'ic_group'],
                      [ns_ui.collapsePrivateNetwork, 'pn_group'],
                      [ns_ui.collapseDns, 'dns_group'],
                      [ns_ui.collapseDynamicDns, 'ddns_group'],
                      [ns_ui.collapseClientConnection, 'client_connection']]:
            try:
                # XXX: passing of the hidden _collapsedstate_ parameter is not too clean
                uihelpers.update_collapse_setting(
                    rdf_uri, fda['%s._collapsedstate_' % key])
            except:
                _log.exception('error updating collapsed state for %s' %
                               rdf_uri)

        # Validation and config generation
        old_vpn_server_address = None
        try:
            # Form global canonicalization
            gc = networkconfigvalidation.ConfigNetworkCanonicalizator(
                ctx, form, data)
            gc.canonicalize_ip_subnet()

            # Form global validation
            gv = networkconfigvalidation.ConfigNetworkValidator(
                ctx, form, data)

            # Check required fields. Some fields may be required because of some other fields value and thus cannot
            # be checked locally.
            gv.check_required_fields()

            gv.ip_and_subnet_match()  # Checks public and private.
            gv.public_private_ip_not_same(
            )  # XXX: warning for now only; worth a warning, but still works to some extent
            gv.public_private_eth_not_same()
            gv.check_single_interface_ok()
            gv.check_interface_default_gateways()
            gv.check_public_subnet(
            )  # XXX: warning for now only, overlaps don't cause runner errors
            gv.check_private_subnet(
            )  # XXX: warning for now only, overlaps don't cause runner errors
            gv.check_uplink()
            gv.check_only_one_proxyarp()
            gv.check_dns_dhcp_valid()
            gv.check_client_settings(
            )  # XXX: some checks commented to warnings for now

            # Intermediate early bail out to avoid saving if there are errors
            gv.finalize_validation()

            # XXX: One interface setup could rename the internet connection tab to
            # network connection,  and update all the selections.

            # Get old VPN server address for comparison
            ui_root = helpers.get_ui_config()
            if ui_root.hasS(ns_ui.vpnServerAddress):
                old_vpn_server_address = ui_root.getS(ns_ui.vpnServerAddress,
                                                      rdf.String)

            # Deep copy UI config to 'new' UI config
            pd.clone_ui_config()

            # Save form data
            self.save_network_data(ctx, form, data)
            self.save_client_connection_data(ctx, form, data)

            # newUiConfig -> newL2tpDeviceConfig
            pd.save_protocol_data()
        except:
            _log.exception(
                'validation failed unexpectedly, adding global error')
            fda.add_global_error('Unknown validation error')

        # Finalize raises exception if there are errors and handles disabled fields as well as copying form data to errors data.
        gv.finalize_validation()

        # Save ok, activate config
        pd.activate_protocol_data()

        # Update initial config saved flag
        pd.update_initial_config_saved()

        # If certificate name has changed, regenerate and re-read cert files
        new_vpn_server_address = None
        ui_root = helpers.get_ui_config()  # reget root after change
        if ui_root.hasS(ns_ui.vpnServerAddress):
            new_vpn_server_address = ui_root.getS(ns_ui.vpnServerAddress,
                                                  rdf.String)

        # XXX: unnecessary to check for None now, but doesn't hurt
        if (old_vpn_server_address != new_vpn_server_address):
            common_name = None
            if (new_vpn_server_address
                    is not None) and (new_vpn_server_address != ''):
                common_name = new_vpn_server_address
            _log.info('regenerating ssl certificates, common name %s' %
                      common_name)

            @db.untransact()
            def _regenerate():
                helpers.generate_self_signed_certificate(
                    constants.WEBUI_PRIVATE_KEY,
                    constants.WEBUI_CERTIFICATE,
                    common_name=common_name)

            _regenerate()

            self.master.reread_ssl_files()
        else:
            _log.debug('certificate name unchanged, not regenerating')

        #
        #  XXX: It would be cleaner if we could first stop the runner, then change the
        #  config, and then restart it.  If we do that with a deferred, then it is possible
        #  that the user changes the config again before we have time to activate it.
        #  Putting the config into some sort of "staging area" might help.  Currently we
        #  simply assume that runner stop (and start) are robust enough.
        #

        # stop, configure, start
        followup = uihelpers.build_uri(ctx, 'status/main.html')
        return uihelpers.reconfigure_and_restart_page(self.master,
                                                      ctx,
                                                      followup_uri=followup)
Ejemplo n.º 23
0
    def save_routes_data(self, ctx, form, data):
        def _save_additional_route_to_rdf(rdf_node, fda):
            uidatahelpers.create_rdf_route(rdf_node, fda['subnet'],
                                           fda['network_connection'],
                                           fda['gateway'], ns_ui.route)

        def _save_ppp_firewall_rule_to_rdf(rdf_node, fda):
            if isinstance(fda['ip_subnet'], datatypes.IPv4Address):
                rdf_node.setS(ns_ui.ipAddress, rdf.IPv4Address,
                              fda['ip_subnet'])
            elif isinstance(fda['ip_subnet'], datatypes.IPv4Subnet):
                rdf_node.setS(ns_ui.subnet, rdf.IPv4Subnet, fda['ip_subnet'])
            else:
                raise uidatahelpers.FormDataError(
                    'Firewall rule IP/subnet is neither IPv4Address nor IPv4Subnet'
                )

            if fda['protocol'] == 'any':
                pass
            else:
                rdf_node.setS(ns_ui.protocol, rdf.String, fda['protocol'])

            uidatahelpers.save_optional_field_to_rdf(rdf_node, ns_ui.port,
                                                     rdf.Integer, fda, 'port')

            rdf_node.setS(ns_ui.action, rdf.String, fda['action'])

        toplevel_fda = formalutils.FormDataAccessor(form, [], ctx)
        ui_root = helpers.get_new_ui_config()

        # Default route
        droute_fda = toplevel_fda.descend('dr_group')
        uidatahelpers.create_rdf_route(ui_root, None,
                                       droute_fda['network_connection'],
                                       droute_fda['gateway'],
                                       ns_ui.defaultRoute)

        # Additional routes
        add_route_fda = toplevel_fda.descend('ar_group')
        uidatahelpers.save_dynamic_list_to_rdf(ui_root, ns_ui.routes,
                                               ns_ui.Route, add_route_fda,
                                               _save_additional_route_to_rdf)

        # Source routing (forced routing)
        source_fda = toplevel_fda.descend('sr_group')
        if source_fda['source_routing_selection'] == 'off':
            ui_root.removeNodes(ns_ui.sourceRouting)
        elif source_fda['source_routing_selection'] == 'on':
            uidatahelpers.create_rdf_route(ui_root, None,
                                           source_fda['network_connection'],
                                           source_fda['gateway'],
                                           ns_ui.sourceRouting)
        else:
            raise uidatahelpers.FormDataError(
                'Forced routing is neither on nor off.')

        # PPP firewall rules
        fwrule_fda = toplevel_fda.descend('fwrule_group')
        uidatahelpers.save_dynamic_list_to_rdf(ui_root, ns_ui.pppFirewallRules,
                                               ns_ui.PppFirewallRule,
                                               fwrule_fda,
                                               _save_ppp_firewall_rule_to_rdf)
Ejemplo n.º 24
0
    def submitted(self, ctx, form, data):
        fda = formalutils.FormDataAccessor(form, [], ctx)
        pd = uidatahelpers.CreateProtocolData()

        # Save collapsed states first, so they feed back to next round
        for [rdf_uri,
             key] in [[ns_ui.collapseLicense, 'license_group'],
                      [ns_ui.collapseLocale, 'locale_group'],
                      [ns_ui.collapseProductMaintenance, 'reboot_group'],
                      [ns_ui.collapseSnmp, 'snmp_group'],
                      [ns_ui.collapseRemoteManagement, 'remote_group'],
                      [ns_ui.collapseSslCertificate, 'ssl_group']]:
            try:
                # XXX: passing of the hidden _collapsedstate_ parameter is not too clean
                uihelpers.update_collapse_setting(
                    rdf_uri, fda['%s._collapsedstate_' % key])
            except:
                _log.exception('error updating collapsed state for %s' %
                               rdf_uri)

        try:
            # global canonicalization
            tmp = fda.descend('license_group')
            if tmp.has_key('license_key') and (tmp['license_key'] is not None):
                tmp['license_key'] = tmp['license_key'].upper().strip()

            # global validation
            tmp = fda.descend('license_group')
            if tmp.has_key('license_key') and (tmp['license_key'] is not None):
                val, grps = None, None
                try:
                    val, grps = licensekey.decode_license(tmp['license_key'])
                except:
                    _log.exception('license decoding failed')
                if val is None:
                    tmp.add_error('license_key', 'Invalid license key')

            tmp = fda.descend('remote_group')
            if tmp.has_key('root_password1') and tmp.has_key('root_password2'):
                pw1, pw2 = tmp['root_password1'], tmp['root_password2']
                if pw1 is None:
                    pw1 = ''
                if pw2 is None:
                    pw2 = ''
                if pw1 != pw2:
                    tmp.add_error('root_password1', 'Passwords do not match')
                    tmp.add_error('root_password2', 'Passwords do not match')
                else:
                    if not helpers.check_unix_password_characters(pw1):
                        tmp.add_error('root_password1',
                                      'Invalid characters in password')
                        tmp.add_error('root_password2',
                                      'Invalid characters in password')

            tmp = fda.descend('snmp_group')
            if tmp.has_key(
                    'snmp_community') and tmp['snmp_community'] is not None:
                if not uihelpers.check_snmp_community_characters(
                        tmp['snmp_community']):
                    tmp.add_error('snmp_community', 'Invalid characters')

            #
            #  XXX -- How to validate SSL certificates reliably?  Currently invalid
            #  certificate / key causes VPNease to use self-signed version so it's
            #  relatively OK.
            #

            #
            #  XXX -- admin smtp setting validation & normalization
            #

            # Intermediate early bail out to avoid saving if there are errors
            fda.finalize_validation()

            # Deep copy UI config to 'new' UI config
            pd.clone_ui_config()

            # save data
            self.save_ui_data(ctx, form, data)

            # re-create protocol data to see if new exceptions crop up
            pd.save_protocol_data()
        except:
            _log.exception(
                'validation failed unexpectedly, adding global error')
            fda.add_global_error('Unknown validation error')

        # finalize; raises if something wrong
        fda.finalize_validation()

        # locale settings are handled directly
        cfg_ui = helpers.get_new_ui_config()
        try:
            cfg_ui.setS(ns_ui.timezone, rdf.String,
                        fda['locale_group.timezone'])
            cfg_ui.setS(ns_ui.keymap, rdf.String, fda['locale_group.keymap'])
            gnomeconfig.set_keymap_settings(
                cfg_ui.getS(ns_ui.keymap, rdf.String))
        except:
            _log.exception('activating timezone and keymap settings failed')

        # same with root password
        try:
            tmp = fda.descend('remote_group')
            if tmp.has_key('root_password1') and tmp.has_key('root_password2'):
                pw1, pw2 = tmp['root_password1'], tmp['root_password2']
                if (pw1 == '') and (pw2 == ''):
                    pass
                elif (pw1 == None) and (pw2 == None):
                    pass
                elif pw1 == pw2:
                    # change password; we assume it converts to ascii nicely
                    helpers.change_unix_password('root', str(pw1))
                else:
                    # should not come here
                    _log.error('passwords differ after validation, ignoring')
        except:
            _log.exception('changing root password failed')

        # activate new config
        pd.activate_protocol_data()

        # update initial config saved flag
        pd.update_initial_config_saved()

        #
        #  XXX: It would be cleaner if we could first stop the runner, then change the
        #  config, and then restart it.  If we do that with a deferred, then it is possible
        #  that the user changes the config again before we have time to activate it.
        #  Putting the config into some sort of "staging area" might help.  Currently we
        #  simply assume that runner stop (and start) are robust enough.
        #

        #
        #  XXX: If timezone has changed, we should re-render graphs immediately so they
        #  will have the correct timezone when status pages are loaded.
        #

        # ssl certificate - always rewrite here
        try:
            uihelpers.update_ssl_certificate_files()

            # reread files; we don't regenerate because we never overwrite the self-signed
            # certificate here
            self.master.reread_ssl_files()
        except:
            _log.exception('ssl certificate check failed')

        # stop, configure, start
        followup = uihelpers.build_uri(ctx, 'status/main.html')
        return uihelpers.reconfigure_and_restart_page(self.master,
                                                      ctx,
                                                      followup_uri=followup)
Ejemplo n.º 25
0
    def save_ui_data(self, ctx, form, data):
        fda = formalutils.FormDataAccessor(form, [], ctx)
        ui_root = helpers.get_new_ui_config()

        # XXX: this should probably be refactored to uihelpers, in conjunction
        # with the access control element
        def _set_access(ns_pub, ns_priv, val):
            _log.debug('_set_access: %s' % val)
            if val == 'both':
                ui_root.setS(ns_pub, rdf.Boolean, True)
                ui_root.setS(ns_priv, rdf.Boolean, True)
            elif val == 'public':
                ui_root.setS(ns_pub, rdf.Boolean, True)
                ui_root.setS(ns_priv, rdf.Boolean, False)
            elif val == 'private':
                ui_root.setS(ns_pub, rdf.Boolean, False)
                ui_root.setS(ns_priv, rdf.Boolean, True)
            else:
                ui_root.setS(ns_pub, rdf.Boolean, False)
                ui_root.setS(ns_priv, rdf.Boolean, False)

        tmp = fda.descend('license_group')
        if tmp.has_key('license_key') and tmp['license_key'] is not None:
            lic_key = tmp['license_key'].upper()
            ui_root.setS(ns_ui.licenseKey, rdf.String, lic_key)
        else:
            # empty field (None) => clear product license
            ui_root.setS(ns_ui.licenseKey, rdf.String, '')

        tmp = fda.descend('locale_group')

        tmp = fda.descend('reboot_group')
        ui_root.setS(ns_ui.periodicRebootDay, rdf.Integer, tmp['reboot_day'])
        ui_root.setS(ns_ui.periodicRebootTime, rdf.Integer, tmp['reboot_time'])
        ui_root.setS(ns_ui.automaticUpdates, rdf.Boolean,
                     tmp['automatic_updates'])

        tmp = fda.descend('snmp_group')
        _set_access(ns_ui.snmpAccessPublic, ns_ui.snmpAccessPrivate,
                    tmp['snmp_access'])
        if tmp.has_key('snmp_community') and tmp['snmp_community'] is not None:
            ui_root.setS(ns_ui.snmpCommunity, rdf.String,
                         tmp['snmp_community'])
        else:
            ui_root.setS(ns_ui.snmpCommunity, rdf.String, '')

        tmp = fda.descend('remote_group')
        _set_access(ns_ui.webAccessPublic, ns_ui.webAccessPrivate,
                    tmp['www_administration'])
        _set_access(ns_ui.sshAccessPublic, ns_ui.sshAccessPrivate,
                    tmp['ssh_connection'])

        tmp = fda.descend('ssl_group')
        if tmp.has_key('ssl_certificate_chain'
                       ) and tmp['ssl_certificate_chain'] is not None:
            ui_root.setS(ns_ui.publicSslCertificateChain, rdf.String,
                         tmp['ssl_certificate_chain'])
        else:
            ui_root.setS(ns_ui.publicSslCertificateChain, rdf.String, '')
        if tmp.has_key(
                'ssl_private_key') and tmp['ssl_private_key'] is not None:
            ui_root.setS(ns_ui.publicSslPrivateKey, rdf.String,
                         tmp['ssl_private_key'])
        else:
            ui_root.setS(ns_ui.publicSslPrivateKey, rdf.String, '')
Ejemplo n.º 26
0
    def form_management(self, ctx):
        form = formal.Form()
        fda = formalutils.FormDataAccessor(form, [], ctx)
        tzhelp = uihelpers.TimezoneHelper()
        txt = self.mng_uitexts

        ### License

        g = formalutils.CollapsibleGroup('license_group',
                                         label=txt.license_group_caption)
        g.setCollapsed(uihelpers.collapse_setting(ns_ui.collapseLicense))
        g.add(
            formalutils.Field('license_key',
                              formal.String(required=False),
                              label=txt.license_key_label))
        form.add(g)

        ### Locale

        tzoptions = []
        for tzname in tzhelp.get_timezones():
            tzoptions.append((tzname, tzname))

        def _tz_cmp(x, y):
            x_name, x_label = x
            y_name, y_label = y
            return unicode.__cmp__(unicode(x_label), unicode(y_label))

        tzoptions.sort(cmp=_tz_cmp)

        # XXX: keymap values are truncated because they are so long
        keymapoptions = []
        for gname, gname_escaped, human in gnomeconfig.get_keymap_list():
            keymapoptions.append(
                (gname_escaped, uihelpers.ui_truncate(human, 56)))

        def _km_cmp(x, y):
            x_name, x_label = x
            y_name, y_label = y
            return unicode.__cmp__(unicode(x_label), unicode(y_label))

        keymapoptions.sort(cmp=_km_cmp)

        g = formalutils.CollapsibleGroup('locale_group',
                                         label='Locale Settings')
        g.setCollapsed(uihelpers.collapse_setting(ns_ui.collapseLocale))
        g.add(
            formalutils.Field('timezone',
                              formal.String(required=True),
                              formal.widgetFactory(formal.SelectChoice,
                                                   options=tzoptions),
                              label='Timezone'))
        g.add(
            formalutils.Field('keymap',
                              formal.String(required=True),
                              formal.widgetFactory(formal.SelectChoice,
                                                   options=keymapoptions),
                              label='Keyboard layout'))

        # XXX: it would be good if we could show a time example using the timezone
        # admin has selected.

        form.add(g)

        ### Reboots

        g = formalutils.CollapsibleGroup('reboot_group',
                                         label=txt.reboot_group_caption)
        g.setCollapsed(
            uihelpers.collapse_setting(ns_ui.collapseProductMaintenance))
        g.add(
            formalutils.Field('reboot_day',
                              formal.Integer(required=True),
                              formal.widgetFactory(
                                  formal.SelectChoice,
                                  options=txt.reboot_day_options),
                              label=txt.reboot_day_label))
        g.add(
            formalutils.Field('reboot_time',
                              formal.Integer(required=True),
                              formal.widgetFactory(
                                  formal.SelectChoice,
                                  options=txt.reboot_time_options),
                              label=txt.reboot_time_label))
        # Information about the periodic reboot consequences (about 5 minutes downtime).
        g.add(
            formalutils.Field('automatic_updates',
                              formal.Boolean(required=True),
                              label=txt.automatic_update_label))
        form.add(g)

        ### SNMP

        g = formalutils.CollapsibleGroup('snmp_group', label='SNMP Monitoring')
        g.setCollapsed(uihelpers.collapse_setting(ns_ui.collapseSnmp))
        g.add(
            uihelpers.create_access_control_dropdown('snmp_access',
                                                     'SNMP read-only access'))
        g.add(
            formalutils.Field('snmp_community',
                              formal.String(required=False),
                              formal.widgetFactory(
                                  formalutils.SemiHiddenPassword),
                              label='SNMP community string (password)'))
        form.add(g)

        ### Remote management

        g = formalutils.CollapsibleGroup('remote_group',
                                         label=txt.remote_group_caption)
        g.setCollapsed(
            uihelpers.collapse_setting(ns_ui.collapseRemoteManagement))
        g.add(
            uihelpers.create_access_control_dropdown('www_administration',
                                                     'Web administration'))
        g.add(
            uihelpers.create_access_control_dropdown('ssh_connection',
                                                     'SSH connection'))
        g.add(
            formalutils.Field('root_password1',
                              formal.String(required=False),
                              formal.widgetFactory(formalutils.HiddenPassword),
                              label='Set root password'))
        g.add(
            formalutils.Field('root_password2',
                              formal.String(required=False),
                              formal.widgetFactory(formalutils.HiddenPassword),
                              label='Re-enter root password'))
        form.add(g)

        ### Admin e-mails

        # XXX: not yet implemented
        #g = formalutils.CollapsibleGroup('email_group', label='Administrator E-mail')
        #g.setCollapsed(uihelpers.collapse_setting(ns_ui.collapseAdminEmail))
        #g.add(formalutils.Field('smtp_server', formal.String(required=False), label='SMTP server'))
        #g.add(formalutils.Field('smtp_from', formal.String(required=False), label='FROM address'))
        #g.add(formalutils.Field('smtp_to', formal.String(required=False), label='TO address(es) (comma separated)'))
        #form.add(g)

        ### SSL certificate

        g = formalutils.CollapsibleGroup('ssl_group', label='SSL Certificate')
        g.setCollapsed(uihelpers.collapse_setting(
            ns_ui.collapseSslCertificate))
        g.add(
            formalutils.Field(
                'ssl_certificate_chain',
                formal.String(required=False),
                formal.widgetFactory(formal.TextArea, cols=80, rows=10),
                label=
                'SSL Certificate Chain (PEM format, server certificate first)')
        )
        g.add(
            formalutils.Field('ssl_private_key',
                              formal.String(required=False),
                              formal.widgetFactory(formal.TextArea,
                                                   cols=80,
                                                   rows=10),
                              label='SSL Private Key (PEM format)'))
        form.add(g)

        ### Submit buttons

        sg = formalutils.SubmitFieldGroup('buttons')
        sg.add(
            formalutils.SubmitField('submit',
                                    formal.String(),
                                    label='Save changes'))
        form.add(sg)
        form.addAction(self.submitted, name='submit', validate=False)

        ### Fill data to form

        try:
            self.fill_management(ctx, fda)
        except:
            # ignore failure so user has chance to edit the form
            _log.exception('fill_form_data failed, ignoring')

        return form
Ejemplo n.º 27
0
    def submitted(self, ctx, form, data):
        fda = formalutils.FormDataAccessor(form, [], ctx)
        pd = uidatahelpers.CreateProtocolData()

        # Save collapsed states first, so they feed back to next round
        for [rdf_uri, key] in [[ns_ui.collapseRadius, 'radius']]:
            try:
                # XXX: passing of the hidden _collapsedstate_ parameter is not too clean
                uihelpers.update_collapse_setting(
                    rdf_uri, fda['%s._collapsedstate_' % key])
            except:
                _log.exception('error updating collapsed state for %s' %
                               rdf_uri)

        old_radius_info = None
        new_radius_info = None
        try:
            # Pre-step: collect usernames and passwords in previous config; we'll need
            # them to deal with password changing correctly.
            userpw_dict = uihelpers.get_user_password_dict()

            # Basic validation
            fda = formalutils.FormDataAccessor(form, ['userlist_group'], ctx)
            self._validate_users(ctx, form, data, userpw_dict)
            self._validate_radius(ctx, form, data)

            # Intermediate early bail out to avoid saving if there are errors
            fda.finalize_validation()

            # Get old runner-critical RADIUS info for comparison
            old_radius_info = self._get_radius_info(new_ui_config=False)

            # Deep copy UI config to 'new' UI config
            pd.clone_ui_config()

            # Save form data to rdf database
            self.save_radius(ctx, form, data)
            self.save_user_list(ctx, form, data, userpw_dict)

            # Get new runner-critical RADIUS info for comparison
            new_radius_info = self._get_radius_info(new_ui_config=True)

            # Save protocol data and finalize validation
            pd.save_protocol_data()
        except:
            _log.exception(
                'validation failed unexpectedly, adding global error')
            fda.add_global_error('Unknown validation error')

        fda.finalize_validation()

        # Check whether a full restart is required or not; although we can edit user
        # information without a full restart (in which case FreeRADIUS is reconfigured
        # and restarted), we can't add, remote, or edit RADIUS server addresses because
        # runner would not get the new server information to its monitoring list.

        _log.debug('old radius info: %s, new radius info: %s' %
                   (old_radius_info, new_radius_info))

        full_restart_required = (old_radius_info != new_radius_info)

        if full_restart_required:
            _log.info('radius servers changed, full restart required')

            # Activate new config
            pd.activate_protocol_data()

            # Update initial config saved flag
            pd.update_initial_config_saved()

            #
            #  XXX: It would be cleaner if we could first stop the runner, then change the
            #  config, and then restart it.  If we do that with a deferred, then it is possible
            #  that the user changes the config again before we have time to activate it.
            #  Putting the config into some sort of "staging area" might help.  Currently we
            #  simply assume that runner stop (and start) are robust enough.
            #

            # stop, configure, start
            followup = uihelpers.build_uri(ctx, 'status/main.html')
            return uihelpers.reconfigure_and_restart_page(
                self.master, ctx, followup_uri=followup)
        else:
            _log.info('radius servers not changed, only freeradius restart')

            # Nuke unwanted PPP connections first time here, so their corresponding
            # protocol config is intact, leading to a clean teardown.
            try:
                pd.recheck_and_drop_ppp_connections()
            except:
                _log.exception('ppp device recheck failed')

            # Activate new config
            # XXX - just change user data here?
            pd.activate_protocol_data()

            # Update initial config saved flag
            pd.update_initial_config_saved()

            try:
                pd.restart_freeradius()  # needs protocol config in place
            except:
                _log.exception('freeradius restart failed')

            # Check again for unwanted PPP devices; teardowns here will currently be ugly
            try:
                pd.recheck_and_drop_ppp_connections()
            except:
                _log.exception('ppp device recheck failed')

            # just a fake activation page
            followup = uihelpers.build_uri(ctx, 'status/main.html')
            return uihelpers.reconfigure_page(self.master,
                                              ctx,
                                              followup_uri=followup)
Ejemplo n.º 28
0
    def _validate_users(self, ctx, form, data, userpw_dict):
        fda = formalutils.FormDataAccessor(form, ['userlist_group'], ctx)
        ui_root = helpers.get_ui_config()

        # user list validation
        idx = 0
        users = []
        while True:
            fda_user = fda.descend(str(idx))
            if len(fda_user.keys()) == 0:
                break
            users.append(fda_user)
            idx += 1

        s2s_server_usernames = []
        if ui_root.hasS(ns_ui.siteToSiteConnections):
            for s2s_conn in ui_root.getS(
                    ns_ui.siteToSiteConnections,
                    rdf.Seq(rdf.Type(ns_ui.SiteToSiteConnection))):
                if s2s_conn.hasS(ns_ui.mode) and s2s_conn.getS(
                        ns_ui.mode, rdf.String) == 'server' and s2s_conn.hasS(
                            ns_ui.username):
                    s2s_server_usernames.append(
                        s2s_conn.getS(ns_ui.username, rdf.String))

        usernames_found = []
        fixed_ips_found = []
        for fda_user_index, fda_user in enumerate(users):
            # username checks
            if fda_user.has_key('username'):
                if not uihelpers.check_ppp_username_characters(
                        fda_user['username']):
                    fda_user.add_error('username', 'Invalid characters')
                else:
                    username = fda_user['username']
                    if username in usernames_found:
                        fda_user.add_error('username', 'Duplicate username')
                    elif username in s2s_server_usernames:
                        fda_user.add_error(
                            'username',
                            'Duplicate username (already a site-to-site server-mode connection of that name)'
                        )
                    elif len(username) > constants.MAX_USERNAME_LENGTH:
                        fda_user.add_error('username', 'Username too long')
                    else:
                        usernames_found.append(username)

            # password chars
            if fda_user.has_key('password') and (fda_user['password']
                                                 is not None):
                if not uihelpers.check_ppp_password_characters(
                        fda_user['password']):
                    fda_user.add_error('password', 'Invalid characters')
                elif len(fda_user['password']) > constants.MAX_PASSWORD_LENGTH:
                    fda_user.add_error('password', 'Password too long')

            # Password is a bit tricky; admin may have changed a username and we don't have
            # any permanent user identifiers that allow us to identify this as the same user
            # and keep its password despite the name change.  So, we require either that the
            # password is set, or that a user previously existed with this username (changed
            # or not !) and use the old password.

            if fda_user.has_key('username') and (fda_user['username'] is not None) and \
                   (not fda_user.has_key('password') or fda_user['password'] is None or fda_user['password'] == ''):
                username = fda_user['username']
                if userpw_dict.has_key(username):
                    # all ok
                    pass
                else:
                    fda_user.add_error('password', 'Required for new users')

            # fixed ip checks

            # XXX: we could also check that the fixed IP is from the
            # PPP subnet to try to prevent admin configuration errors,
            # but this would be too restrictive and is currently not
            # done: a warning would help here.

            if fda_user.has_key('fixed_ip') and (
                    fda_user['fixed_ip']
                    is not None) and (fda_user['fixed_ip'] != ''):
                fixed_ip_errors = False
                fixed_ip = fda_user['fixed_ip']

                iprange = ui_root.getS(ns_ui.clientAddressRange,
                                       rdf.IPv4AddressRange)
                pppsubnet = ui_root.getS(ns_ui.clientSubnet, rdf.IPv4Subnet)

                # The fixed IP may not overlap with other users fixed IP addresses
                if fixed_ip.toString() in fixed_ips_found:
                    fda_user.add_error('fixed_ip',
                                       'Duplicate fixed IP address')
                    fixed_ip_errors = True

                # Check restricted addresses inside PPP subnet
                if pppsubnet.inSubnet(fixed_ip):
                    # The fixed IP must not be from the PPP address range (dynamic allocation pool)
                    if iprange.inRange(fixed_ip):
                        fda_user.add_error(
                            'fixed_ip', 'Overlaps with client address range')
                        fixed_ip_errors = True

                    if fixed_ip < pppsubnet.getFirstUsableAddress():
                        fda_user.add_error(
                            'fixed_ip',
                            'First address of the client subnet prohibited')
                        fixed_ip_errors = True
                    elif fixed_ip == pppsubnet.getLastUsableAddress():
                        fda_user.add_error(
                            'fixed_ip',
                            'Last usable address of the client subnet prohibited'
                        )
                        fixed_ip_errors = True
                    elif fixed_ip > pppsubnet.getLastUsableAddress():
                        fda_user.add_error(
                            'fixed_ip',
                            'Last address of the client subnet prohibited')
                        fixed_ip_errors = True

                if not fixed_ip_errors:
                    fixed_ips_found.append(fixed_ip.toString())
Ejemplo n.º 29
0
    def submitted(self, ctx, form, data):
        fda = formalutils.FormDataAccessor(form, [], ctx)
        pd = uidatahelpers.CreateProtocolData()

        # Save collapsed states first, so they feed back to next round
        for [rdf_uri,
             key] in [[ns_ui.collapseDefaultRoute, 'dr_group'],
                      [ns_ui.collapseAdditionalRoutes, 'ar_group'],
                      [ns_ui.collapseSourceRouting, 'sr_group'],
                      [ns_ui.collapsePppFirewallRules, 'fwrule_group'],
                      [ns_ui.collapsePortForwardingRules, 'port_forwards'],
                      [ns_ui.collapseFirewall, 'firewall']]:
            try:
                # XXX: passing of the hidden _collapsedstate_ parameter is not too clean
                uihelpers.update_collapse_setting(
                    rdf_uri, fda['%s._collapsedstate_' % key])
            except:
                _log.exception('error updating collapsed state for %s' %
                               rdf_uri)

        # Validation and config generation
        try:
            # Form global canonicalization
            gc = networkconfigvalidation.ConfigNetworkCanonicalizator(
                ctx, form, data)

            # Form global validation
            gv = networkconfigvalidation.ConfigNetworkValidator(
                ctx, form, data)

            # Check required fields. Some fields may be required because of some other fields value and thus cannot
            # be checked locally.
            gv.check_required_fields_routingfirewall()

            # Global checks for internet and private network connection.
            gv.check_route_destination_valid(
            )  # just checks that some destination is defined, not that e.g. private network exists
            gv.check_ppp_firewall_rules()

            # Intermediate early bail out to avoid saving if there are errors
            gv.finalize_validation()

            # XXX: we might want to add warnings here later if route subnets overlap with each other
            # or with site-to-site subnets

            # Deep copy UI config to 'new' UI config
            pd.clone_ui_config()

            # Save form data.
            self.save_routes_data(ctx, form, data)
            self.save_firewall_data(ctx, form, data)

            pd.save_protocol_data()
        except:
            _log.exception(
                'validation failed unexpectedly, adding global error')
            fda.add_global_error('Unknown validation error')

        # Finalize raises exception if there are errors and handles disabled fields as well as copying form data to erros data.
        gv.finalize_validation()

        # Save ok, activate config
        pd.activate_protocol_data()

        # Update initial config saved flag
        pd.update_initial_config_saved()

        #
        #  XXX: It would be cleaner if we could first stop the runner, then change the
        #  config, and then restart it.  If we do that with a deferred, then it is possible
        #  that the user changes the config again before we have time to activate it.
        #  Putting the config into some sort of "staging area" might help.  Currently we
        #  simply assume that runner stop (and start) are robust enough.
        #

        # stop, configure, start
        followup = uihelpers.build_uri(ctx, 'status/main.html')
        return uihelpers.reconfigure_and_restart_page(self.master,
                                                      ctx,
                                                      followup_uri=followup)
Ejemplo n.º 30
0
    def submitted_select_target(self, ctx, form, data):
        print 'submitted_select_target'

        # XXX: target selection error messages as constants?
        fda = formalutils.FormDataAccessor(form, [], ctx)
        target = None
        recovery = False
        large_install = False
        try:
            target = form.data['selecttarget.target']
            print 'selected target: %s' % target

            medium = mediahelper.get_media().get_medium_by_device_name(target)
            if medium.get_size() < constants.DISK_SIZE_MINIMUM:
                fda.add_error('selecttarget.target',
                              'Minimum target medium size is 2 GB')
            if medium.is_write_protected():
                fda.add_error('selecttarget.target',
                              'Target medium is write-protected')

            if form.data.has_key('selecttarget.recovery'):
                recovery = form.data['selecttarget.recovery']

            if medium.get_size(
            ) >= constants.DISK_SIZE_MINIMUM_FOR_LARGE_INSTALL:
                large_install = True
        except:
            fda.add_error('selecttarget.target',
                          'Target medium cannot be selected')
        fda.finalize_validation()

        root = livecddb.get_livecd_database_root()
        root.setS(ns_ui.targetDevice, rdf.String, target)
        root.setS(ns_ui.attemptRecovery, rdf.Boolean, recovery)
        root.removeNodes(ns_ui.previousConfigurationRdfXml)
        root.removeNodes(ns_ui.previousInstalledVersion)

        # Recovery check here
        if recovery:
            print 'attempting recovery from %s' % target

            try:
                prev_cfg, prev_version = installhelpers.recover_existing_configuration(
                    target)
                if prev_cfg is not None:
                    root.setS(ns_ui.previousConfigurationRdfXml, rdf.String,
                              prev_cfg.encode('hex'))

                    if prev_version is not None:
                        root.setS(ns_ui.previousInstalledVersion, rdf.String,
                                  prev_version)
                    else:
                        pass
                else:
                    raise Exception('did not find recovery data')
            except:
                print 'recovery failed'

        # Select installation model based on target size
        root.setS(ns_ui.installLargeDisk, rdf.Boolean, large_install)

        print livecddb.dump_livecd_database()
        request = inevow.IRequest(ctx)
        request.redirect(request.URLPath().sibling('installconfirm.html'))
        return ''