def main(): """ CLI for connecting to the Magic Network """ print("\t") log("M a g i c", color="blue", figlet=True) print("\t") log("Welcome to Magic", "green") print("\t") network_manager = NetworkManager() account_manager = AccountManager() network_daemon = NetworkMonitor(10) # Setup initial user account data account_manager.get_critical_info() # Let developers choose the ssid of the magic network they'd like to connect to. if DEV: network_manager.get_custom_network_ssid() # Make sure any profiles or wpa_supplicants are installed. account_manager.setup_8021x_creds(network_manager.ssid) # Kick off connection process network_manager.connect() signal.signal(signal.SIGTERM, sighandler) signal.signal(signal.SIGINT, sighandler)
def connect(self): # TODO: Find networks with the best signal, and connect to that one only. log("Magically connecting to the best network...", "yellow") with yaspin(): self.wireless.connect(self.ssid) # TODO: Ping some endpoint until connectivity is guaranteed? log("You're connected! Enjoy your magic internet.")
def install_8021x_creds(self, ssid, address, signature, timestamp): mobileconfig_name = self.get_mobileconfig_name(ssid, address) response = cmd( 'nmcli con add type wifi ifname %s con-name %s ssid %s ipv4.method auto 802-1x.eap ttls 802-1x.phase2-auth pap 802-1x.identity %s 802-1x.password %s-%s 802-11-wireless-security.key-mgmt wpa-eap' % (self.interface(), mobileconfig_name, ssid, address, timestamp, signature)) if not response.returncode == 0: log("An error occured: %s" % response.stdout, "red") return False return True
def run(self): self.resume() while True: with self.state: if self.paused: # Block execution until notified. self.state.wait() log("Checking for connection", "yellow") time.sleep(self.interval)
def __init__(self, interface=None): # Detect the platform's driver self._driver_name = self.detect_driver() if self._driver_name == 'networksetup': from magic.wireless.driver.macos_networksetup import MacOSNetworksetup self._driver = MacOSNetworksetup() elif self._driver_name == 'nmcli': from magic.wireless.driver.linux_nmcli import LinuxNmcli self._driver = LinuxNmcli() else: # TODO: Windows support log("Your OS is not supported yet.", "red") # Raise an error if interface cannot be determined if self.interface() is None: raise Exception('Unable to auto-detect the network interface.')
def install_8021x_creds(self, ssid, address, signature, timestamp): template_env = Environment(loader=FileSystemLoader(RESOURCES_PATH)) mobileconfig_name = self.get_mobileconfig_name(ssid, address) print("python radiusauth.py -s /tmp/magicsock %s %s-%s" % (address, timestamp, signature)) rendered_mobileconfig = template_env.get_template( 'magic.mobileconfig.template').render(address=address, signature=signature, ssid=ssid, name=mobileconfig_name, timestamp=timestamp) log( "As a first time user, Magic will install a network profile to make connecting to the network easier.", "blue") try: passwd_prompt = get_prompt([{ 'type': 'password', 'message': 'Enter your computer password', 'name': 'password' }]) passwd = passwd_prompt.get('password') + "\n" except Exception as error: raise Exception("An error occured: %s" % error) mobileconfig_filename = "%s.mobileconfig" % mobileconfig_name mobileconfig_file = open( "%s/%s" % (RESOURCES_PATH, mobileconfig_filename), "w") mobileconfig_file.write(rendered_mobileconfig) mobileconfig_file.close() response = cmd( "profiles install -path=%s/%s -user=%s" % (RESOURCES_PATH, mobileconfig_filename, getpass.getuser()), True, passwd.encode()) # Remove generated mobileconfig remove("%s/%s" % (RESOURCES_PATH, mobileconfig_filename)) if not response.returncode == 0: log("An error occured: %s" % response.stdout, "red") return False
def get_custom_network_ssid(self): with yaspin(): ssids = self.wireless.scan() if not ssids: log("Could not find any magic ssids!", "red") sys.exit(1) answers = get_prompt([{ 'type': 'list', 'name': 'ssid', 'message': '(DEV) Select a magic ssid format:', 'choices': ssids, 'filter': lambda val: val.lower() }]) self.ssid = answers.get('ssid')
def start(self): installed_profile = self.get_profile() if not installed_profile: log("As a first time user, Magic will install a network profile to make connecting to the network easier.", "blue") passwd_question = [{ 'type': 'password', 'message': 'Enter your computer password', 'name': 'password' }] try: passwd_prompt = get_prompt(passwd_question) self.install_profile(passwd_prompt.get('password') + "\n") except Exception as error: raise Exception("An error occured: %s" % error)
def get_critical_info(self): answers = get_prompt([ { 'type': 'list', 'name': 'onboard_account_choice', 'message': 'Ethereum Setup:', 'choices': [ { "name": "Create a new test Ethereum account", "value": "new_account" }, { "name": "Enter existing test account using your test private key.", "value": "existing_account" }, { "name": "Exit Magic CLI", "value": "graceful_exit" } ] }, { 'type': 'password', 'name': 'eth_privkey', 'when': lambda answers: answers['onboard_account_choice'] == "existing_account", 'message': 'Enter private key' }]) try: if answers['onboard_account_choice'] == "new_account": account = generate_account() self.address = account.address self.privkey = account.privkey log("Your new address: %s" % self.address, "blue") log("Your new private key: %s" % self.privkey, "blue") if answers['onboard_account_choice'] == "existing_account": self.privkey = answers['eth_privkey'] if answers['onboard_account_choice'] == "graceful_exit": log('Goodbye!', 'green') exit() self.onboarded = True except KeyboardInterrupt: log('Goodbye!', 'green') exit()
def sighandler(signum, frame): if signum == signal.SIGTERM: log("Got SIGTERM. Shutting down.", "red") context.y = True elif signum == signal.SIGINT: log("Got SIGINT. Shutting down.", "red") context.y = True else: log("Signal %d not handled" % signum, "red")
def associate(self, ssid): response = cmd("nmcli con up %s" % ssid) if not response.returncode == 0: log("An error occured: %s" % response.stdout, "red") return False return True
def pause(self): with self.state: log("Pausing monitor", "magenta") self.paused = True
def resume(self): with self.state: log("Resuming monitor", "green") self.paused = False self.state.notify()
def install_profile(passwd): response = cmd("profiles install -path=magic/resources/magic.mobileconfig -user=%s" % getpass.getuser(), True, passwd.encode()) if not response.returncode == 0: log("An error occured: %s" % response.stdout, "red")