Пример #1
0
    def management_connection_down(self, reason=None):  # from managementconnection
        _log.info("management connection down, reason: %s" % reason)

        try:
            helpers.get_global_status().setS(ns.managementServerConnection, rdf.Boolean, False)
        except:
            _log.exception("cannot set management connection rdf status to down")

        # 'reason' can be many things, including protocol errors from Identify(),
        # check for them here
        try:
            self._license_helper.process_failure_reason(reason)
        except:
            _log.exception("failed to check management_connection_down reason")

        self._ajax_helper.wake_status_change_waiters()
Пример #2
0
    def _write_connection_state(self, identify_result):
        behind_nat = identify_result["behindNat"]
        our_addr = identify_result["clientAddressSeenByServer"]

        global_st = helpers.get_global_status()
        global_st.setS(ns.behindNat, rdf.Boolean, behind_nat)
        global_st.setS(
            ns.managementConnectionOurNattedAddress, rdf.IPv4Address, datatypes.IPv4Address.fromString(our_addr)
        )
Пример #3
0
    def _get_server_ip_for_win2k(self, ctx):
        try:
            request = inevow.IRequest(ctx)
            server_address = str(request.getRequestHostname())
            t = datatypes.IPv4Address.fromString(server_address)
            return t.toString()
        except:  # XXX: wide catch
            pass

        # use management connection natted IP
        global_st = helpers.get_global_status()
        if global_st.hasS(ns.managementConnectionOurNattedAddress):
            return global_st.getS(ns.managementConnectionOurNattedAddress, rdf.IPv4Address).toString()

        return None
Пример #4
0
        def _get_hardware_info():
            cpu_usage = None
            mem_usage = None
            disk_usage = None
            swap_usage = None

            try:
                st_root = helpers.get_global_status()
                cpu_usage = st_root.getS(ns.cpuUsage, rdf.Float)
                mem_usage = st_root.getS(ns.memoryUsage, rdf.Float)
                disk_usage = st_root.getS(ns.diskUsage, rdf.Float)
                swap_usage = st_root.getS(ns.swapUsage, rdf.Float)
            except:
                _log.exception("cannot get values")

            return [cpu_usage, disk_usage, mem_usage, swap_usage]
Пример #5
0
    def create_config(self, cfg, resinfo):
        """Create configuration file for ez-ipupdate.

        See http://www.shakabuku.org/writing/dyndns.html.
        """

        global_st = helpers.get_global_status()
        pub_iface, pub_iface_name = helpers.get_public_iface(cfg)
        pub_dyndns_cfg = helpers.get_dyndns_config(cfg)

        conf = textwrap.dedent("""\
        # intentionally empty
        """)

        self.do_start = False
        if pub_dyndns_cfg is not None:
            self.debug_on = helpers.get_debug(cfg)
            if self.debug_on:
                debug = 'debug'
            else:
                debug = ''

            self._log.debug('Dynamic DNS configured')
            provider = pub_dyndns_cfg.getS(ns.provider, rdf.String)
            username = pub_dyndns_cfg.getS(ns.username, rdf.String)
            password = pub_dyndns_cfg.getS(ns.password, rdf.String)
            hostname = pub_dyndns_cfg.getS(ns.hostname, rdf.String)

            # address selection is complicated due to many options
            address = None
            if pub_dyndns_cfg.hasS(ns.dynDnsAddress):
                addr = pub_dyndns_cfg.getS(ns.dynDnsAddress)
                if addr.hasType(ns.DynDnsInterfaceAddress):
                    address = None
                elif addr.hasType(ns.DynDnsStaticAddress):
                    address = addr.getS(ns.ipAddress, rdf.IPv4Address).toString()
                elif addr.hasType(ns.DynDnsManagementConnectionAddress):
                    if global_st.hasS(ns.managementConnectionOurNattedAddress):
                        address = global_st.getS(ns.managementConnectionOurNattedAddress, rdf.IPv4Address).toString()
                    else:
                        address = None
                else:
                    raise Exception('invalid dynDnsAddress type')
            if address == '':
                address = None
            address_str = ''
            if address is not None:
                address_str = 'address=%s' % address
                
            interface_str = 'interface=%s' % pub_iface_name
                
            self._log.debug('Dynamic DNS parameters: provider=%s, username=%s, password=%s, hostname=%s, address=%s, interface=%s' % (provider, username, password, hostname, address, pub_iface_name))

            # NB: persistent cache is required for proper dyndns operation
            
            conf = textwrap.dedent("""\
            #!/usr/local/bin/ez-ipupdate -c

            service-type=%(provider)s
            user=%(username)s:%(password)s
            host=%(hostname)s
            %(address)s
            %(interface)s
            max-interval=2073600
            %(debug)s
            cache-file=%(cache_file_stem)s.%(pubif)s
            daemon
            """) % {'provider':provider,
                    'username':username,
                    'password':password,
                    'hostname':hostname,
                    'address':address_str,
                    'interface':interface_str,
                    'cache_file_stem':constants.EZIPUPDATE_CACHE,
                    'pubif':pub_iface_name,
                    'debug':debug}

            self.do_start = True
        else:
            self._log.debug('No dynamic DNS configured')

        self.configs = [{'file': constants.EZIPUPDATE_CONF,
                         'cont': conf,
                         'mode': 0755}]
Пример #6
0
    def renderHTTP(self, ctx):
        # XXX: refactor this to a helper??
        def _xml_escape(x):
            return helpers.xml_escape(x)

        # XXX: simple base64 encoding does not seem to be enough
        def _base64_encode(x):
            # base64 produces a newline, strip it away; still not correct tho
            return x.encode('base64').strip()

        request = inevow.IRequest(ctx)

        # figure parameters
        server_address = ''
        try:
            server_address = str(request.getRequestHostname())
        except:
            _log.exception('cannot figure out server_address')

        preshared_key = ''
        try:
            psk_seq = helpers.get_ui_config().getS(
                ns_ui.preSharedKeys, rdf.Seq(rdf.Type(ns_ui.PreSharedKey)))
            preshared_key = str(psk_seq[0].getS(ns_ui.preSharedKey,
                                                rdf.String))
        except:
            _log.exception('cannot figure out preshared_key')

        username = ''
        try:
            tmp = self.get_logged_in_username()
            if tmp is not None:
                username = str(tmp)
        except:
            _log.exception('cannot figure out username')

        # Profile name
        profile_prefix = 'VPNease'
        try:
            if os.path.exists(constants.AUTOCONFIG_PROFILE_PREFIX_FILE):
                profile_prefix = helpers.read_and_strip_file(
                    constants.AUTOCONFIG_PROFILE_PREFIX_FILE)
        except:
            _log.exception('failed when checking for alternative profile name')
        profile_name = '%s (%s)' % (profile_prefix, server_address)

        # Server behind port forward
        server_portfw = False
        try:
            global_st = helpers.get_global_status()
            if global_st.hasS(ns.behindNat):
                if global_st.getS(ns.behindNat, rdf.Boolean):
                    server_portfw = True
                else:
                    server_portfw = False
            else:
                # assume worst - reboot *MAY* be required
                server_portfw = True

            # markerfile for debugging
            if helpers.check_marker_file(
                    constants.FORCE_NATTREBOOT_MARKERFILE):
                _log.warning(
                    'force nat-t reboot marker file exists, pretending server is behind port forward'
                )
                server_portfw = True
        except:
            _log.exception(
                'cannot determine whether server is behind port forward, may be OK'
            )

        #
        #  Notes about OSX plist for networkConnect
        #
        #    * There are settings for PPP redial counts etc.  We don't use them
        #      because we want to minimize risks.
        #
        #    * DisconnectOnXXX settings only seem to work when inside SystemConfig,
        #      not inside UserConfigs.
        #
        #    * SystemConfig -> IPv4 -> OverridePrimary=1 should, based on PPP code,
        #      set 'default route' setting but doesn't seem to work.
        #
        #    * UserConfigs -> IPsec -> ExportedSharedSecret contains the pre-shared
        #      key for IKE in some sort of encrypted format.  The value is base64
        #      encoded but the pre-shared key is processed (encrypted or masked)
        #      prior to base64.  Note that whatever the unknown (and seemingly
        #      undocumented transform is, it has to be reversible because IKE needs
        #      the PSK.
        #
        #    * CCP / MPPC / MPPE are disabled now.  They don't actually work in
        #      Leopard at least.
        #

        # create xml plist
        textdata = textwrap.dedent("""\
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
            <plist version="1.0">
                <dict>
                    <key>L2TP</key>
                    <dict>
                        <key>SystemConfig</key>
                        <dict>
                            <key>PPP</key>
                            <dict>
                                <key>DisconnectOnSleep</key>
                                <integer>1</integer>
                                <key>DisconnectOnFastUserSwitch</key>
                                <integer>1</integer>
                                <key>DisconnectOnLogout</key>
                                <integer>1</integer>
                            </dict>
                        </dict>

                        <key>UserConfigs</key>
                        <array>
                            <dict>
                                <key>EAP</key>
                                <dict/>
                                <key>IPSec</key>
                                <dict>
                                    <key>AuthenticationMethod</key>
                                    <string>SharedSecret</string>
                                    <key>LocalIdentifier</key>
                                    <string></string>
                                    <key>LocalIdentifierType</key>
                                    <string>KeyID</string>
                                </dict>
                                <key>PPP</key>
                                <dict>
                                    <key>AuthName</key>
                                    <string>%(username)s</string>
                                    <key>CommRemoteAddress</key>
                                    <string>%(server_address)s</string>
                                    <key>UserDefinedName</key>
                                    <string>%(profile_name)s</string>
                                    <key>CCPEnabled</key>
                                    <integer>%(ccp_enabled)d</integer>
                                    <key>CCPMPPE128Enabled</key>
                                    <integer>%(ccp_mppe40_enabled)d</integer>
                                    <key>CCPMPPE40Enabled</key>
                                    <integer>%(ccp_mppe128_enabled)d</integer>
                                </dict>
                            </dict>
                        </array>
                    </dict>
                </dict>
            </plist>
        """) % {
            'preshared_key_base64': _xml_escape(_base64_encode(preshared_key)),
            'username': _xml_escape(username),
            'server_address': _xml_escape(server_address),
            'profile_name': _xml_escape(profile_name),
            'override_primary': 1,  # XXX: force default route
            'ccp_enabled': 0,
            'ccp_mppe40_enabled': 0,
            'ccp_mppe128_enabled': 0,
        }

        #
        #  Content-Type is interesting.  If this is served as 'text/xml', Safari
        #  will display the file without offering a save option.  Even if it is
        #  saved, Safari will *refuse* saving the file with '.networkConnect'
        #  extension.
        #
        #  'application/octet-stream' causes Safari to save the file, and use can
        #  double click to run it.
        #

        return uihelpers.UncachedData(textdata, 'application/octet-stream')
Пример #7
0
    def renderHTTP(self, ctx):
        # XXX: refactor this to a helper??
        def _xml_escape(x):
            return helpers.xml_escape(x)

        # XXX: simple base64 encoding does not seem to be enough
        def _base64_encode(x):
            # base64 produces a newline, strip it away; still not correct tho
            return x.encode('base64').strip()

        request = inevow.IRequest(ctx)

        # figure parameters
        server_address = ''
        try:
            server_address = str(request.getRequestHostname())
        except:
            _log.exception('cannot figure out server_address')
            
        preshared_key = ''
        try:
            psk_seq = helpers.get_ui_config().getS(ns_ui.preSharedKeys, rdf.Seq(rdf.Type(ns_ui.PreSharedKey)))
            preshared_key = str(psk_seq[0].getS(ns_ui.preSharedKey, rdf.String))
        except:
            _log.exception('cannot figure out preshared_key')

        username = ''
        try:
            tmp = self.get_logged_in_username()
            if tmp is not None:
                username = str(tmp)
        except:
            _log.exception('cannot figure out username')
            
        # Profile name
        profile_prefix = 'VPNease'
        try:
            if os.path.exists(constants.AUTOCONFIG_PROFILE_PREFIX_FILE):
                profile_prefix = helpers.read_and_strip_file(constants.AUTOCONFIG_PROFILE_PREFIX_FILE)
        except:
            _log.exception('failed when checking for alternative profile name')
        profile_name = '%s (%s)' % (profile_prefix, server_address)

        # Server behind port forward
        server_portfw = False
        try:
            global_st = helpers.get_global_status()
            if global_st.hasS(ns.behindNat):
                if global_st.getS(ns.behindNat, rdf.Boolean):
                    server_portfw = True
                else:
                    server_portfw = False
            else:
                # assume worst - reboot *MAY* be required
                server_portfw = True

            # markerfile for debugging
            if helpers.check_marker_file(constants.FORCE_NATTREBOOT_MARKERFILE):
                _log.warning('force nat-t reboot marker file exists, pretending server is behind port forward')
                server_portfw = True
        except:
            _log.exception('cannot determine whether server is behind port forward, may be OK')
            
        #
        #  Notes about OSX plist for networkConnect
        #
        #    * There are settings for PPP redial counts etc.  We don't use them
        #      because we want to minimize risks.
        #
        #    * DisconnectOnXXX settings only seem to work when inside SystemConfig,
        #      not inside UserConfigs.
        #
        #    * SystemConfig -> IPv4 -> OverridePrimary=1 should, based on PPP code,
        #      set 'default route' setting but doesn't seem to work.
        #
        #    * UserConfigs -> IPsec -> ExportedSharedSecret contains the pre-shared
        #      key for IKE in some sort of encrypted format.  The value is base64
        #      encoded but the pre-shared key is processed (encrypted or masked)
        #      prior to base64.  Note that whatever the unknown (and seemingly
        #      undocumented transform is, it has to be reversible because IKE needs
        #      the PSK.
        #
        #    * CCP / MPPC / MPPE are disabled now.  They don't actually work in
        #      Leopard at least.
        #
        
        # create xml plist
        textdata = textwrap.dedent("""\
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
            <plist version="1.0">
                <dict>
                    <key>L2TP</key>
                    <dict>
                        <key>SystemConfig</key>
                        <dict>
                            <key>PPP</key>
                            <dict>
                                <key>DisconnectOnSleep</key>
                                <integer>1</integer>
                                <key>DisconnectOnFastUserSwitch</key>
                                <integer>1</integer>
                                <key>DisconnectOnLogout</key>
                                <integer>1</integer>
                            </dict>
                        </dict>

                        <key>UserConfigs</key>
                        <array>
                            <dict>
                                <key>EAP</key>
                                <dict/>
                                <key>IPSec</key>
                                <dict>
                                    <key>AuthenticationMethod</key>
                                    <string>SharedSecret</string>
                                    <key>LocalIdentifier</key>
                                    <string></string>
                                    <key>LocalIdentifierType</key>
                                    <string>KeyID</string>
                                </dict>
                                <key>PPP</key>
                                <dict>
                                    <key>AuthName</key>
                                    <string>%(username)s</string>
                                    <key>CommRemoteAddress</key>
                                    <string>%(server_address)s</string>
                                    <key>UserDefinedName</key>
                                    <string>%(profile_name)s</string>
                                    <key>CCPEnabled</key>
                                    <integer>%(ccp_enabled)d</integer>
                                    <key>CCPMPPE128Enabled</key>
                                    <integer>%(ccp_mppe40_enabled)d</integer>
                                    <key>CCPMPPE40Enabled</key>
                                    <integer>%(ccp_mppe128_enabled)d</integer>
                                </dict>
                            </dict>
                        </array>
                    </dict>
                </dict>
            </plist>
        """) % {
            'preshared_key_base64': _xml_escape(_base64_encode(preshared_key)),
            'username': _xml_escape(username),
            'server_address': _xml_escape(server_address),
            'profile_name': _xml_escape(profile_name),
            'override_primary': 1, # XXX: force default route
            'ccp_enabled': 0,
            'ccp_mppe40_enabled': 0,
            'ccp_mppe128_enabled': 0,
            }
        
        #
        #  Content-Type is interesting.  If this is served as 'text/xml', Safari
        #  will display the file without offering a save option.  Even if it is
        #  saved, Safari will *refuse* saving the file with '.networkConnect'
        #  extension.
        #
        #  'application/octet-stream' causes Safari to save the file, and use can
        #  double click to run it.
        #

        return uihelpers.UncachedData(textdata, 'application/octet-stream')
Пример #8
0
    def measure_and_update(self, update_rrd=True, update_rdf=True, quick=False):
        """Update all measurements.

        To minimize rrd load on the system, it is preferable to update all measurements
        in one go.  Further, if asynchronous updating is desired, separate rrd files
        need to be used anyway.

        We also update some statistics to a RDF status branch for statistics that are not
        protocol related (e.g. CPU usage).  This is so that the web UI can get access to
        this sort of information even when the runner is not active.  Admittedly this is
        not a very clean thing to do.
        """
    
        # It is important to run time-consuming system checks inside @untransact to
        # minimize the time RDF database access is locked.
        
        timestamp = datetime.datetime.utcnow()
        timeval = int(time.mktime(timestamp.timetuple()))  # XXX: round?

        # these values can be extracted regardless of l2tp-runner state
        cpu_load = self.measure_cpuload()
        if quick:
            # quick is used in boot to minimize postinit time
            cpu_usage = 0
        else:
            cpu_usage = self.measure_vmstat()
        cpu_count = self.measure_cpuinfo()
        disk_total, disk_avail = self.measure_diskstats()
        mem_total, mem_free, swap_total, swap_free = self.measure_meminfo()
        mem_used = mem_total - mem_free
        swap_used = swap_total - swap_free
        net_pubrx, net_pubtx, net_privrx, net_privtx = self.measure_network()

        def _nusr_filter(dev):
            if dev.hasS(ns.restrictedConnection) and dev.getS(ns.restrictedConnection, rdf.Boolean):
                return False
            # XXX: We'd like to ignore inactive devices, but this wasn't reliable enough
            #if dev.hasS(ns.deviceActive) and not dev.getS(ns.deviceActive, rdf.Boolean):
            #    return False
            if dev.hasS(ns.connectionType):
                if dev.getS(ns.connectionType).hasType(ns.NormalUser):
                    return True
            return False

        def _susr_filter(dev):
            if dev.hasS(ns.restrictedConnection) and dev.getS(ns.restrictedConnection, rdf.Boolean):
                return False
            # XXX: We'd like to ignore inactive devices, but this wasn't reliable enough
            #if dev.hasS(ns.deviceActive) and not dev.getS(ns.deviceActive, rdf.Boolean):
            #    return False
            if dev.hasS(ns.connectionType):
                conntype = dev.getS(ns.connectionType)
                if conntype.hasType(ns.SiteToSiteClient) or conntype.hasType(ns.SiteToSiteServer):
                    return True
            return False

        # user related data is only reliable if l2tp-runner is in state "running"
        try:
            st = helpers.get_status().getS(ns.state)
            if not st.hasType(ns.StateRunning):
                raise Exception('State not running')

            nusr_count, \
                        nusr_rxtotal, nusr_txtotal, \
                        nusr_rxavg, nusr_txavg, \
                        nusr_rxmax, nusr_txmax = self.measure_ppp_devs(_nusr_filter)

            susr_count, \
                        susr_rxtotal, susr_txtotal, \
                        susr_rxavg, susr_txavg, \
                        susr_rxmax, susr_txmax = self.measure_ppp_devs(_susr_filter)
        except:
            nusr_count, \
                        nusr_rxtotal, nusr_txtotal, \
                        nusr_rxavg, nusr_txavg, \
                        nusr_rxmax, nusr_txmax = ['U']*7
            
            susr_count, \
                        susr_rxtotal, susr_txtotal, \
                        susr_rxavg, susr_txavg, \
                        susr_rxmax, susr_txmax = ['U']*7

        vals = [ timeval,
                 cpu_load,
                 cpu_usage,
                 cpu_count,
                 disk_total,
                 disk_avail,
                 mem_total,
                 mem_used,
                 swap_total,
                 swap_used,
                 net_pubrx,
                 net_pubtx,
                 net_privrx,
                 net_privtx,
                 nusr_count,
                 nusr_rxtotal,
                 nusr_txtotal,
                 nusr_rxavg,
                 nusr_txavg,
                 nusr_rxmax,
                 nusr_txmax,
                 susr_count,
                 susr_rxtotal,
                 susr_txtotal,
                 susr_rxavg,
                 susr_txavg,
                 susr_rxmax,
                 susr_txmax ]
                 
        valstr = map(lambda x: str(x), vals)

        @db.untransact()
        def _run_rrd():
            # update rrd
            run_command([
                constants.CMD_RRDTOOL,
                'update', self.filename,
                ':'.join(valstr)
                ], retval=runcommand.FAIL)

        if update_rrd:
            _run_rrd()

        if update_rdf:
            st = helpers.get_global_status()
            st.setS(ns.cpuUsage, rdf.Float, float(cpu_usage))  # percents
            st.setS(ns.cpuCount, rdf.Integer, int(cpu_count))  # count
            st.setS(ns.diskUsage, rdf.Float, (float(disk_total) - float(disk_avail)) / float(disk_total) * 100.0)  # percents
            st.setS(ns.diskTotal, rdf.Float, float(disk_total))  # fake megs
            st.setS(ns.memoryUsage, rdf.Float, float(mem_used) / float(mem_total) * 100.0)  # percents
            st.setS(ns.memoryTotal, rdf.Integer, int(mem_total))  # kilobytes
            if swap_total > 0:
                st.setS(ns.swapUsage, rdf.Float, float(swap_used) / float(swap_total) * 100.0)  # percents
            else:
                st.setS(ns.swapUsage, rdf.Float, 0.0)
            st.setS(ns.swapTotal, rdf.Integer, int(swap_total))  # kilobytes
Пример #9
0
    def management_connection_up(self, identify_result):  # from managementconnection
        _log.info("management connection established")

        if identify_result is None:
            _log.warning("identify result is None, connect() or start_primary() called twice? ignoring")
            return

        try:
            helpers.write_cookie_uuid(identify_result["cookieUuid"])
        except:
            _log.exception("failed to write cookie UUID")

        try:
            self._license_helper.update_license_info(identify_result)
        except:
            _log.exception("license info update failed")

        try:
            self._update_update_info(identify_result)
        except:
            _log.exception("update update info failed")

        try:
            self._do_timesync(identify_result["currentUtcTime"])
        except:
            _log.exception("timesync failed")

        try:
            self._immediate_auto_update_check(identify_result)
        except:
            _log.exception("immediate auto update check failed")

        try:
            self._write_connection_state(identify_result)
        except:
            _log.exception("write connection state failed")

        # XXX: If license parameters have changed, we might ideally want to
        # make the protocol part react somehow.  Currently we just apply the
        # changed license to new connections, not old ones.

        # Wake up Ajax waiters
        self._ajax_helper.wake_status_change_waiters()

        # Boot code (update) needs a snapshot of a "known good" network config.
        # If the management connection comes up, we are quite sure the config
        # is good, at least for updating.
        if self.l2tpmanager.isRunning():
            try:
                self._export_rdf_database()
            except:
                _log.exception("failed to export rdf database")

        # If we don't have a test license at this point, request one now
        try:
            self._test_license_check()
        except:
            _log.exception("_test_license_check failed")

        # XXX: to ensure that the test license makes it to the exported "known good"
        # configuration ASAP, we might want to export the known good configuration
        # again when the test license is received.

        try:
            helpers.get_global_status().setS(ns.managementServerConnection, rdf.Boolean, True)
        except:
            _log.exception("cannot set management connection rdf status to up")
Пример #10
0
 def _update_license_server_status(res):
     helpers.get_global_status().setS(ns.managementServerConnection, rdf.Boolean, False)
Пример #11
0
    def renderHTTP(self, ctx):
        request = inevow.IRequest(ctx)

        # read unpatched exe
        f = None
        exedata = ''
        try:
            f = open(self.autoconfig_exe_filename, 'rb')
            exedata = f.read()
        finally:
            if f is not None:
                f.close()
                f = None

        # figure parameters
        server_address_in_uri = None
        try:
            server_address_in_uri = str(request.getRequestHostname())
        except:
            _log.exception('cannot figure out server_address_in_uri')

        server_ip = None
        try:
            server_ip = self._get_server_ip_for_win2k(ctx)
        except:
            _log.exception('cannot figure out server_ip')

        server_address = None
        if self.force_server_address_to_ip:
            server_address = server_ip
        else:
            server_address = server_address_in_uri

        if (server_address_in_uri is None) or (server_address_in_uri == ''):
            raise Exception('server_address_in_uri missing, failing')
        if (server_address is None) or (server_address == ''):
            raise Exception('server_address missing, failing')
        if self.include_win2k_regdata and ((server_ip is None) or (server_ip == '')):
            raise Exception('server_ip is needed and missing, failing')
        
        preshared_key = ''
        try:
            psk_seq = helpers.get_ui_config().getS(ns_ui.preSharedKeys, rdf.Seq(rdf.Type(ns_ui.PreSharedKey)))
            preshared_key = str(psk_seq[0].getS(ns_ui.preSharedKey, rdf.String))
        except:
            _log.exception('cannot figure out preshared_key')

        username = ''
        try:
            tmp = self.get_logged_in_username()
            if tmp is not None:
                username = str(tmp)
        except:
            _log.exception('cannot figure out username')
            
        # Profile name, always uses address in URI, even if server address itself forced to IP
        profile_prefix = 'VPNease'
        try:
            if os.path.exists(constants.AUTOCONFIG_PROFILE_PREFIX_FILE):
                profile_prefix = helpers.read_and_strip_file(constants.AUTOCONFIG_PROFILE_PREFIX_FILE)
        except:
            _log.exception('failed when checking for alternative profile name')
        profile_name = '%s (%s)' % (profile_prefix, server_address_in_uri)

        # Server behind port forward
        server_portfw = False
        try:
            global_st = helpers.get_global_status()
            if global_st.hasS(ns.behindNat):
                if global_st.getS(ns.behindNat, rdf.Boolean):
                    server_portfw = True
                else:
                    server_portfw = False
            else:
                # assume worst - reboot *MAY* be required
                server_portfw = True

            # markerfile for debugging
            if helpers.check_marker_file(constants.FORCE_NATTREBOOT_MARKERFILE):
                _log.warning('force nat-t reboot marker file exists, pretending server is behind port forward')
                server_portfw = True
        except:
            _log.exception('cannot determine whether server is behind port forward, may be OK')

        # Windows 2000 registry-based IPsec policy + prohibitIpsec
        win2k_ipsec_policy_registry_file = ''
        try:
            if self.include_win2k_regdata:
                # Registry data is HEX encoded UTF-16; HEX encoding is used to avoid problems
                # with the parameters.cpp mechanism (null termination).  The resulting data is
                # large, around 50 kilobytes (!).

                # Always uses server IP for IPsec policy, because that's what Windows 2000 IPsec wants
                t = self._get_win2k_reg_file(server_ip, preshared_key)
                t = self._encode_windows_reg_file(t)  # UTF-16
                win2k_ipsec_policy_registry_file = t.encode('hex')  # hex-encoded UTF-16
        except:
            _log.exception('cannot create win2k registry file')
        
        # Fill paramdict and return
        paramdict = {}
        paramdict['operation'] = 'configure_profile'
        paramdict['profile_name'] = profile_name
        paramdict['desktop_shortcut_name'] = '%s.LNK' % profile_name  # xxx: for now the same
        paramdict['server_address'] = server_address
        paramdict['preshared_key'] = preshared_key
        paramdict['username'] = username
        paramdict['ppp_compression_enabled'] = '1'
        paramdict['default_route_enabled'] = '1'
        paramdict['create_desktop_shortcut'] = '1'
        paramdict['open_profile_after_creation'] = '1'
        if server_portfw:
            paramdict['server_behind_port_forward'] = '1'
        else:
            paramdict['server_behind_port_forward'] = '0'
        if self.include_win2k_regdata:
            paramdict['win2k_registry_file'] = win2k_ipsec_policy_registry_file
        return uihelpers.RewritingBinaryResource(exedata, paramdict)
Пример #12
0
def _update_snmp():
    """Update SNMP data."""

    from codebay.l2tpserver import licensemanager
    from codebay.l2tpserver import helpers
    from codebay.l2tpserver.webui import uihelpers

    now = datetime.datetime.utcnow()
    st = helpers.get_status()
    global_st = helpers.get_global_status()
    license_info = helpers.get_license_info()

    def _timeticks(td):
        return int(helpers.timedelta_to_seconds(td) * 100.0)

    def _timestamp(dt):
        return datatypes.encode_datetime_to_iso8601_subset(dt)

    def _get_management_conn():
        # XXX: not the best place for this
        if global_st.hasS(ns.managementServerConnection):
            if global_st.getS(ns.managementServerConnection, rdf.Boolean):
                return 1
        return 0
        
    vals = {}

    lm = licensemanager.LicenseMonitor()
    usr_count, usr_limit, usr_limit_leeway, s2s_count, s2s_limit, s2s_limit_leeway = None, None, None, None, None, None
    try:
        usr_count, usr_limit, usr_limit_leeway, s2s_count, s2s_limit, s2s_limit_leeway = lm.count_both_users()
    except:
        _log.exception('cannot get ppp counts for snmp')

    # XXX: this sharing of status code is quite unclean; see uihelpers.get_status_and_substatus() for suggestions
    health_errors = 0
    try:
        status_class, status_text, substatus_class, substatus_text, status_ok = uihelpers.get_status_and_substatus()
        if status_ok:
            health_errors = 0
        else:
            health_errors = 1
    except:
        _log.exception('cannot determine health errors')
    
    for k, l in [ ('vpneaseHealthCheckErrors',       lambda: health_errors),
                  ('vpneaseUserCount',               lambda: usr_count),
                  ('vpneaseSiteToSiteCount',         lambda: s2s_count),
                  ('vpneaseLastMaintenanceReboot',   lambda: _timestamp(helpers.read_datetime_marker_file(constants.LAST_AUTOMATIC_REBOOT_MARKER_FILE))),
                  ('vpneaseNextMaintenanceReboot',   lambda: _timestamp(uihelpers.compute_periodic_reboot_time())),
                  ('vpneaseLastSoftwareUpdate',      lambda: _timestamp(helpers.read_datetime_marker_file(constants.LAST_SUCCESSFUL_UPDATE_MARKER_FILE))),
                  ('vpneaseSoftwareVersion',         lambda: helpers.get_product_version(cache=True, filecache=True)),
                  ('vpneaseCpuUsage',                lambda: int(global_st.getS(ns.cpuUsage, rdf.Float))),
                  ('vpneaseMemoryUsage',             lambda: int(global_st.getS(ns.memoryUsage, rdf.Float))),
                  ('vpneaseVirtualMemoryUsage',      lambda: int(global_st.getS(ns.swapUsage, rdf.Float))),
                  ('vpneaseServiceUptime',           lambda: _timeticks(now - st.getS(ns.startTime, rdf.Datetime))),
                  ('vpneaseHostUptime',              lambda: _timeticks(datetime.timedelta(0, helpers.get_uptime(), 0))),
                  ('vpneasePublicAddress',           lambda: st.getS(ns.publicInterface, rdf.Type(ns.NetworkInterface)).getS(ns.ipAddress, rdf.IPv4AddressSubnet).getAddress().toString()),
                  ('vpneasePublicSubnet',            lambda: st.getS(ns.publicInterface, rdf.Type(ns.NetworkInterface)).getS(ns.ipAddress, rdf.IPv4AddressSubnet).getMask().toString()),
                  ('vpneasePublicMac',               lambda: st.getS(ns.publicInterface, rdf.Type(ns.NetworkInterface)).getS(ns.macAddress, rdf.String)),
                  ('vpneasePrivateAddress',          lambda: st.getS(ns.privateInterface, rdf.Type(ns.NetworkInterface)).getS(ns.ipAddress, rdf.IPv4AddressSubnet).getAddress().toString()),
                  ('vpneasePrivateSubnet',           lambda: st.getS(ns.privateInterface, rdf.Type(ns.NetworkInterface)).getS(ns.ipAddress, rdf.IPv4AddressSubnet).getMask().toString()),
                  ('vpneasePrivateMac',              lambda: st.getS(ns.privateInterface, rdf.Type(ns.NetworkInterface)).getS(ns.macAddress, rdf.String)),
                  ('vpneaseLicenseKey',              lambda: license_info.getS(ns_ui.licenseKey, rdf.String)),
                  ('vpneaseLicenseString',           lambda: license_info.getS(ns_ui.licenseString, rdf.String)),
                  ('vpneaseLicenseUserLimit',        lambda: usr_limit),
                  ('vpneaseLicenseSiteToSiteLimit',  lambda: s2s_limit),
                  ('vpneaseMaintenanceReboots',      lambda: global_st.getS(ns.periodicReboots, rdf.Integer)),
                  ('vpneaseWatchdogReboots',         lambda: global_st.getS(ns.watchdogReboots, rdf.Integer)),
                  ('vpneaseLicenseServerConnection', _get_management_conn),
                  ]:
        try:
            val = l()
            if val is not None:
                vals[k] = val
        except:
            # these are expected in several cases, so don't spew too much log about them
            # XXX: it would be better if the checkers would figure these out for themselves
            # (when a value is expected and when not)
            _log.info('failed to get snmp value for key %s' % k)
            #_log.exception('failed to get snmp value for key %s' % k)
                  
    keys = vals.keys()
    keys.sort()
    res = ''
    for k in keys:
        res += '%s=%s\n' % (k, vals[k])

    # to ASCII, escaping any non-ASCII chars with XML escapes
    res = res.encode('US-ASCII', 'xmlcharrefreplace')

    f = None
    try:
        f = open(constants.SNMP_DATA_FILE, 'wb')
        f.write(res)
    finally:
        if f:
            f.close()
        f = None