Esempio n. 1
0
def save_options(program, interface, argv, tmp=False):
    """Saves program options.

  Persistence options are stripped before saving to prevent rewriting identical
  options when they are loaded and run.

  Args:
    program: The program for which to save options.
    interface: The interface for which to save options.
    argv: The options to save.
    tmp: Whether to save options to /tmp or _CONFIG_DIR.
  """
    to_save = {
        'argv': [arg for arg in argv if arg not in ('-P', '--persist')],
        'env': {},
    }

    # Also save important environment variables.
    if program == 'hostapd' and 'WIFI_PSK' in os.environ:
        to_save['env']['WIFI_PSK'] = utils.validate_and_sanitize_psk(
            os.environ['WIFI_PSK'])
    if program == 'wpa_supplicant' and 'WIFI_CLIENT_PSK' in os.environ:
        to_save['env']['WIFI_CLIENT_PSK'] = utils.validate_and_sanitize_psk(
            os.environ['WIFI_CLIENT_PSK'])

    utils.atomic_write(
        utils.get_filename(program,
                           utils.FILENAME_KIND.options,
                           interface,
                           tmp=tmp), repr(to_save))
Esempio n. 2
0
def _maybe_restart_hostapd(interface, config, opt):
    """Starts or restarts hostapd unless doing so would be a no-op.

  The no-op case (i.e. hostapd is already running with an equivalent config) can
  be overridden with --force-restart.

  Args:
    interface: The interface on which to start hostapd.
    config: A hostapd configuration, as a string.
    opt: The OptDict parsed from command line options.

  Returns:
    Whether hostapd was started successfully.

  Raises:
    BinWifiException: On various errors.
  """
    tmp_config_filename = utils.get_filename('hostapd',
                                             utils.FILENAME_KIND.config,
                                             interface,
                                             tmp=True)
    forced = False
    current_config = None

    try:
        with open(tmp_config_filename) as tmp_config_file:
            current_config = tmp_config_file.read()
    except IOError:
        pass

    if not _is_hostapd_running(interface):
        utils.log('hostapd not running yet, starting.')
    elif current_config != config:
        utils.log('hostapd config changed, restarting.')
    elif opt.force_restart:
        utils.log('Forced restart requested.')
        forced = True
    else:
        utils.log('hostapd-%s already configured and running', interface)
        return True

    if not _stop_hostapd(interface):
        raise utils.BinWifiException("Couldn't stop hostapd")

    # Set or unset 4-address mode.  This has to be done while hostapd is down.
    utils.log('%s 4-address mode', 'Enabling' if opt.wds else 'Disabling')
    iw.set_4address_mode(interface, opt.wds)

    # We don't want to try to rewrite this file if this is just a forced restart.
    if not forced:
        utils.atomic_write(tmp_config_filename, config)

    if not _start_hostapd(interface, tmp_config_filename, opt.band, opt.ssid):
        utils.log(
            'hostapd failed to start.  Look at hostapd logs for details.')
        return False

    return True
Esempio n. 3
0
    def confirm_job(self,
                    job_data,
                    status='ok',
                    status_message='',
                    admin_message=''):
        status_data = {"status": status}

        if status_message:
            status_data["status_message"] = status_message

        if admin_message:
            status_data["admin_message"] = admin_message

        job_data.update(status_data)

        try:
            data = json.dumps(job_data, separators=(',', ':'))
        except (JSONDecodeError, ValueError) as err:
            self.logger.critical("Failed to create output json: {}".format(
                str(err)))
        else:
            confirm_file_name = join(self.job_folder,
                                     self.current_job + Ninja.CONFIRM_FILE_EXT)

            if atomic_write(data, confirm_file_name):
                self.logger.info(
                    "Confirmation file successfully written: {}".format(
                        confirm_file_name))
            else:
                self.logger.critical(
                    "Failed to create confirmation file: {}".format(
                        confirm_file_name))
        def atomic_save():
            try:
                path = os.path.join(self.directory, '{0}.{1}'.format(filename, self.serializer.name or 'custom'))
                with atomic_write(path, 'wb') as handle:
                    self.serializer.dump(data, handle)

                return True
            except (OSError, IOError):
                return False
        def atomic_save():
            try:
                path = os.path.join(
                    self.directory,
                    '{0}.{1}'.format(filename, self.serializer.name
                                     or 'custom'))
                with atomic_write(path, 'wb') as handle:
                    self.serializer.dump(data, handle)

                return True
            except (OSError, IOError):
                return False
        def atomic_save():
            try:
                data = {}
                data.update(self)

                with lock(self._path):
                    with atomic_write(self._path, 'wb') as handle:
                        json.dump(data, handle, sort_keys=True, indent=2, encoding='utf-8')

                return True
            except (OSError, IOError):
                return False
        def atomic_save():
            try:
                data = {}
                data.update(self)

                with lock(self._path):
                    with atomic_write(self._path, 'wb') as handle:
                        json.dump(data,
                                  handle,
                                  sort_keys=True,
                                  indent=2,
                                  encoding='utf-8')

                return True
            except (OSError, IOError):
                return False
        def atomic_save():
            try:
                path = os.path.join(
                    self.directory,
                    '{0}.{1}'.format(filename, self.serializer.name
                                     or 'custom'))
                settings = os.path.join(self.workflow.directory,
                                        'settings.json')
                if path == settings:
                    raise SerializationException(
                        'Settings file is maintained automatically')

                with atomic_write(path, 'wb') as handle:
                    self.serializer.dump(data, handle)

                return True
            except (OSError, IOError):
                return False
Esempio n. 9
0
def _set_wpa_supplicant_config(interface, config, opt):
    """Starts or restarts wpa_supplicant unless doing so would be a no-op.

  The no-op case (i.e. wpa_supplicant is already running with an equivalent
  config) can be overridden with --force-restart.

  Args:
    interface: The interface on which to start wpa_supplicant.
    config: A wpa_supplicant configuration, as a string.
    opt: The OptDict parsed from command line options.

  Returns:
    Whether wpa_supplicant was started successfully.

  Raises:
    BinWifiException: On various errors.
  """
    tmp_config_filename = utils.get_filename('wpa_supplicant',
                                             utils.FILENAME_KIND.config,
                                             interface,
                                             tmp=True)
    forced = False
    current_config = None
    band = opt.band

    try:
        with open(tmp_config_filename) as tmp_config_file:
            current_config = tmp_config_file.read()
    except IOError:
        pass

    already_running = _is_wpa_supplicant_running(interface)
    if not already_running:
        utils.log('wpa_supplicant not running yet, starting.')
    elif current_config != config:
        # TODO(rofrankel): Consider using wpa_cli reconfigure here.
        utils.log('wpa_supplicant config changed, reconfiguring.')
    elif opt.force_restart:
        utils.log('Forced restart requested.')
        forced = True
    else:
        utils.log('wpa_supplicant-%s already configured and running',
                  interface)
        return True

    if not forced:
        utils.atomic_write(tmp_config_filename, config)

    # TODO(rofrankel): Consider removing all the restart hostapd stuff when
    # b/30140131 is resolved.  hostapd seems to keep working without being
    # restarted, at least on Camaro.
    restart_hostapd = False
    ap_interface = iw.find_interface_from_band(band, iw.INTERFACE_TYPE.ap,
                                               opt.interface_suffix)
    if _is_hostapd_running(ap_interface):
        restart_hostapd = True
        opt_without_persist = options.OptDict({})
        opt_without_persist.persist = False
        opt_without_persist.band = opt.band
        opt_without_persist.interface_suffix = opt.interface_suffix
        if not stop_ap_wifi(opt_without_persist):
            raise utils.BinWifiException(
                "Couldn't stop hostapd to start wpa_supplicant.")

    if already_running:
        subprocess.check_call(['ifdown', interface])
        subprocess.check_call(
            ['/etc/ifplugd/ifplugd.action', interface, 'down'])
        if not _reconfigure_wpa_supplicant(interface):
            raise utils.BinWifiException(
                'Failed to reconfigure wpa_supplicant.')
        subprocess.check_call(['ifup', interface])
        subprocess.check_call(['/etc/ifplugd/ifplugd.action', interface, 'up'])
    elif not _start_wpa_supplicant(interface, tmp_config_filename):
        raise utils.BinWifiException(
            'wpa_supplicant failed to start.  Look at wpa_supplicant logs for '
            'details.')

    if restart_hostapd:
        _restart_hostapd(ap_interface)

    return True
Esempio n. 10
0
def set_wifi(opt):
    """Set up an access point in response to the 'set' command.

  Args:
    opt: The OptDict parsed from command line options.

  Returns:
    Whether setting up the AP succeeded.

  Raises:
    BinWifiException: On various errors.
  """
    band = opt.band
    width = opt.width
    channel = opt.channel
    autotype = opt.autotype
    protocols = set(opt.protocols.split('/'))

    utils.validate_set_wifi_options(opt)

    psk = None
    if opt.encryption == 'WEP' or '_PSK_' in opt.encryption:
        psk = os.environ['WIFI_PSK']

    if band == '5' and quantenna.set_wifi(opt):
        return True

    if iw.RUNNABLE_WL() and not iw.RUNNABLE_IW():
        _set_wifi_broadcom(opt)
        return True

    if not iw.RUNNABLE_IW():
        raise utils.BinWifiException("Can't proceed without iw")

    # If this phy is running client mode, we need to use its width/channel.
    phy = iw.find_phy(band, channel)
    if phy is None:
        raise utils.BinWifiException('no wifi phy for band=%s channel=%s',
                                     band, channel)

    # Check for calibration errors on ath10k.
    qca9880_cal.qca8990_calibration()
    mwifiex.set_recovery(experiment.enabled('MwifiexFirmwareRecovery'))

    client_interface = iw.find_interface_from_phy(phy,
                                                  iw.INTERFACE_TYPE.client,
                                                  opt.interface_suffix)
    if (client_interface is not None
            and _is_wpa_supplicant_running(client_interface)):
        # Wait up to ten seconds for interface width and channel to be available
        # (only relevant if wpa_supplicant was started recently).
        # TODO(rofrankel): Consider shortcutting this loop if wpa_cli shows status
        # is SCANNING (and other values)?
        utils.log(
            'Client running on same band; finding its width and channel.')
        for _ in xrange(50):
            client_band = _get_wpa_band(client_interface)
            client_width, client_channel = iw.find_width_and_channel(
                client_interface)

            sys.stderr.write('.')
            sys.stderr.flush()
            if None not in (client_band, client_width, client_channel):
                band, width, channel = client_band, client_width, client_channel
                utils.log(
                    'Using band=%s, channel=%s, width=%s MHz from client',
                    band, channel, width)
                break
            time.sleep(0.2)
        else:
            utils.log("Couldn't find band, width, and channel used by client "
                      "(it may not be connected)")

    interface = iw.find_interface_from_phy(phy, iw.INTERFACE_TYPE.ap,
                                           opt.interface_suffix)
    if interface is None:
        raise utils.BinWifiException(
            'no wifi interface found for band=%s channel=%s suffix=%s', band,
            channel, opt.interface_suffix)

    for ap_interface in iw.find_all_interfaces_from_phy(
            phy, iw.INTERFACE_TYPE.ap):
        if not _is_hostapd_running(ap_interface):
            continue

        if ap_interface == interface:
            continue

        # TODO(rofrankel):  Figure out what to do about width.  Unlike channel,
        # there's no 'auto' default; we don't know if 20 was requested or just
        # defaulted to.  So it's not clear whether to override the other AP's
        # choice.
        _, other_ap_channel = iw.find_width_and_channel(ap_interface)
        if channel == 'auto':
            channel = other_ap_channel
        else:
            _restart_hostapd(ap_interface, '-c', channel)

    utils.log('interface: %s', interface)
    utils.log('Configuring cfg80211 wifi.')

    pid_filename = utils.get_filename('hostapd',
                                      utils.FILENAME_KIND.pid,
                                      interface,
                                      tmp=True)
    utils.log('pidfile: %s', pid_filename)

    autotype_filename = '/tmp/autotype.%s' % interface
    band_filename = '/tmp/band.%s' % interface
    width_filename = '/tmp/width.%s' % interface
    autochan_filename = '/tmp/autochan.%s' % interface

    old_autotype = utils.read_or_empty(autotype_filename)
    old_band = utils.read_or_empty(band_filename)
    old_width = utils.read_or_empty(width_filename)

    # Special case: if autochannel enabled and we've done it before, just use the
    # old autochannel.  The main reason for this is we may not be able to run the
    # autochannel algorithm without stopping hostapd first, which defeats the code
    # that tries not to restart hostapd unnecessarily.
    if (channel == 'auto' and
        (autotype, band, width) == (old_autotype, old_band, old_width)):
        # ...but only if not forced mode.  If it's forced, don't use the old
        # value, but don't wipe it either.
        if not opt.force_restart:
            autochan = utils.read_or_empty(autochan_filename)
            if autochan and int(autochan) > 0:
                utils.log('Reusing old autochannel=%s', autochan)
                channel = autochan
    else:
        # forget old autochannel setting
        if os.path.exists(autochan_filename):
            try:
                os.remove(autochan_filename)
            except OSError:
                utils.log('Failed to remove autochan file.')

    if channel == 'auto':
        utils.atomic_write(autochan_filename, '')
        try:
            channel = autochannel.scan(interface, band, autotype, width)
        except ValueError as e:
            raise utils.BinWifiException('Autochannel scan failed: %s', e)
        utils.atomic_write(autochan_filename, channel)

    utils.atomic_write(autotype_filename, autotype)
    utils.atomic_write(band_filename, band)
    utils.atomic_write(width_filename, width)

    utils.log('using channel=%s', channel)

    try:
        utils.log('getting phy info...')
        with open(os.devnull, 'w') as devnull:
            try:
                phy_info = subprocess.check_output(('iw', 'phy', phy, 'info'),
                                                   stderr=devnull)
            except subprocess.CalledProcessError as e:
                raise utils.BinWifiException(
                    'Failed to get phy info for phy %s: %s', phy, e)
        hostapd_config = configs.generate_hostapd_config(
            phy_info, interface, band, channel, width, protocols, psk, opt)
    except ValueError as e:
        raise utils.BinWifiException('Invalid option: %s', e)

    return _maybe_restart_hostapd(interface, hostapd_config, opt)
Esempio n. 11
0
def main():
    """The entrypoint for osg-incommon-cert-request
    """
    global args
    try:
        args = parse_cli()

        config_parser = ConfigParser.ConfigParser()
        config_parser.readfp(StringIO(CONFIG_TEXT))
        CONFIG = dict(config_parser.items('InCommon'))

        if args.orgcode:
            codes = [code.strip() for code in args.orgcode.split(',')]
            CONFIG['organization'] = codes[0]
            CONFIG['department'] = codes[1]

        print("Using organization code of %s and department code of %s" %
              (CONFIG['organization'], CONFIG['department']))

        utils.check_permissions(args.write_directory)

        if args.test:
            print("Beginning testing mode: ignoring optional parameters.")
            print("=" * 60)

        # Creating SSLContext with cert and key provided
        # usercert and userprivkey are already validated by utils.findusercred
        ssl_context = cert_utils.get_ssl_context(usercert=args.usercert,
                                                 userkey=args.userprivkey)

        restclient = InCommonApiClient(CONFIG['apiurl'], ssl_context)

        if args.test:
            test_incommon_connection(CONFIG, restclient)
            restclient.close_connection()
            sys.exit(0)

        print("Beginning certificate request")
        print("=" * 60)

        #Create tuple(s) either with a single hostname and altnames or with a set of hostnames and altnames from the hostfile
        if args.hostname:
            hosts = [tuple([args.hostname.strip()] + args.altnames)]
        else:
            with open(args.hostfile, 'rb') as hosts_file:
                host_lines = hosts_file.readlines()
            hosts = [
                tuple(line.split()) for line in host_lines if line.strip()
            ]

        requests = list()
        csrs = list()

        print(
            "The following Common Name (CN) and Subject Alternative Names (SANS) have been specified: "
        )
        # Building the lists with certificates --> utils.Csr(object)
        for host in set(hosts):
            common_name = host[0]
            sans = host[1:]

            print("CN: %s, SANS: %s" % (common_name, sans))
            csr_obj = cert_utils.Csr(common_name,
                                     output_dir=args.write_directory,
                                     altnames=sans)

            logger.debug(csr_obj.x509request.as_text())
            csrs.append(csr_obj)

        print("=" * 60)

        for csr in csrs:
            subj = str(csr.x509request.get_subject())
            print("Requesting certificate for %s: " % subj)
            response_request = submit_request(CONFIG,
                                              restclient,
                                              subj,
                                              csr.base64_csr(),
                                              sans=csr.altnames)

            # response_request stores the sslId for the certificate request
            if response_request:
                requests.append(tuple([response_request, subj]))
                print("Request successful. Writing key file at: %s" %
                      csr.keypath)
                csr.write_pkey()
            else:
                print("Request failed for %s" % subj)

            print("-" * 60)

        # Closing the restclient connection before going idle waiting for approval
        restclient.close_connection()

        print("%s certificate(s) was(were) requested successfully." %
              len(requests))
        print("Waiting %s seconds for requests approval..." % WAIT_APPROVAL)
        time.sleep(WAIT_APPROVAL)

        print("\nStarting certificate retrieval")
        print("=" * 60)
        # Certificate retrieval has to retry until it gets the certificate
        # A restclient (InCommonApiClient) needs to be created for each retrieval attempt
        for request in requests:
            subj = request[1]
            print("Retrieving certificate for %s: " % subj)
            response_retrieve = retrieve_cert(CONFIG, ssl_context, request[0])

            if response_retrieve is not None:
                cert_path = os.path.join(args.write_directory,
                                         subj.split("=")[1] + '-cert.pem')
                print("Retrieval successful. Writing certificate file at: %s" %
                      cert_path)
                utils.safe_rename(cert_path)
                utils.atomic_write(cert_path, response_retrieve)
                os.chmod(cert_path, 0644)
            else:
                print("Retrieval failure for %s" % subj)
                print(
                    "The certificate can be retrieved directly from the InCommon Cert Manager interface."
                )
                print("CN %s, Self-enrollment Certificate ID (sslId): %s" %
                      (subj, request[0]))

            print("-" * 60)

    except SystemExit:
        raise
    except ValueError as exc:
        sys.exit(exc)
    except KeyboardInterrupt as exc:
        print(str(exc))
        sys.exit('''Interrupted by user\n''')
    except KeyError as exc:
        print(prog + ": error: " + "Key %s not found in dictionary" % exc)
        sys.exit(1)
    except FileNotFoundException as exc:
        print(prog + ": error: " + str(exc) + ':' + exc.filename)
        sys.exit(1)
    except SSLError as exc:
        print(prog + ": " + str(exc))
        sys.exit('Please check for valid certificate.\n')
    except (IOError, FileWriteException, BadPassphraseException,
            AttributeError, EnvironmentError, ValueError, EOFError, SSLError,
            AuthenticationFailureException) as exc:
        print(prog + ": error: " + str(exc))
        sys.exit(1)
    except httplib.HTTPException as exc:
        print(str(exc))
        sys.exit(1)
    except Exception:
        traceback.print_exc()
        sys.exit(1)
    sys.exit(0)