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))
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
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
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
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)
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)