diff --git a/aif.xsd b/aif.xsd index a5dc867..b40187f 100644 --- a/aif.xsd +++ b/aif.xsd @@ -422,38 +422,25 @@ - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -465,6 +452,7 @@ + diff --git a/aif/network/_common.py b/aif/network/_common.py index 3887d06..ba61e3e 100644 --- a/aif/network/_common.py +++ b/aif/network/_common.py @@ -65,22 +65,29 @@ def convertPSK(ssid, passphrase): def convertWifiCrypto(crypto_xmlobj, ssid): - crypto = {'type': crypto_xmlobj.find('type').text.strip()} + crypto = {'type': crypto_xmlobj.find('type').text.strip(), + 'auth': {}} + creds_xml = crypto_xmlobj.xpath('psk|enterprise')[0] # if crypto['type'] in ('wpa', 'wpa2', 'wpa3'): if crypto['type'] in ('wpa', 'wpa2'): - crypto['mode'] = crypto_xmlobj.find('mode') - if not crypto['mode']: + crypto['mode'] = creds_xml.tag + if crypto['mode'] == 'psk': crypto['mode'] = 'personal' - else: - crypto['mode'] = crypto['mode'].text.strip() else: crypto['mode'] = None - creds = crypto_xmlobj.find('creds') - crypto['auth'] = {'type': creds.attrib.get('type', 'psk').strip()} - if crypto['auth']['type'] == 'psk': - crypto['auth']['passphrase'] = creds.text.strip('\r').strip('\n') - crypto['auth']['psk'] = convertPSK(ssid, creds.text) + if crypto['mode'] == 'personal': + psk_xml = creds_xml.find('psk') + if aif.utils.xmlBool(psk_xml.attrib.get('isKey', 'false')): + try: + crypto['auth']['passphrase'] = psk_xml.text.strip('\r').strip('\n') + except UnicodeDecodeError: + raise ValueError('WPA-PSK passphrases must be ASCII') + crypto['auth']['psk'] = convertPSK(ssid, crypto['auth']['passphrase']) + else: + crypto['auth']['psk'] = psk_xml.text.strip().lower() # TODO: enterprise support + # elif crypto['mode'] == 'enterprise': + # pass return(crypto) @@ -230,7 +237,7 @@ class BaseConnection(object): self.routes[addrtype].append(addrset) return() - def _writeConnCfg(self, chroot_base = None): + def _writeConnCfg(self, chroot_base): # Dummy method. pass return() diff --git a/aif/network/net.py b/aif/network/net.py index 8580b6f..937bf40 100644 --- a/aif/network/net.py +++ b/aif/network/net.py @@ -34,7 +34,9 @@ class Network(object): fh.write('{0}\n'.format(self.hostname)) os.chown(cfg, 0, 0) os.chmod(cfg, 0o0644) - # TODO: symlinks for systemd for provider - # TODO: writeConf for provider - + for iface in self.connections: + for src, dest in iface.services.items(): + realdest = os.path.join(chroot_base, dest) + os.symlink(src, realdest) + iface.writeConf(chroot_base) return() diff --git a/aif/network/networkd.py b/aif/network/networkd.py index 85186a1..5c7a291 100644 --- a/aif/network/networkd.py +++ b/aif/network/networkd.py @@ -128,7 +128,7 @@ class Wireless(Connection): self._initCfg() def _initConnCfg(self): - self._wpasupp['ssid'] = self.xml.attrib['essid'] + self._wpasupp['ssid'] = '"{0}"'.format(self.xml.attrib['essid']) hidden = aif.utils.xmlBool(self.xml.attrib.get('hidden', 'false')) if hidden: self._wpasupp['scan_ssid'] = 1 @@ -138,20 +138,33 @@ class Wireless(Connection): bssid = None if bssid: bssid = aif.network._common.canonizeEUI(bssid) - self._cfg['BASE']['AP'] = bssid + self._wpasupp['bssid'] = bssid + self._wpasupp['bssid_whitelist'] = bssid crypto = self.xml.find('encryption') if crypto: crypto = aif.network._common.convertWifiCrypto(crypto, self._cfg['BASE']['ESSID']) # if crypto['type'] in ('wpa', 'wpa2', 'wpa3'): + # TODO: WPA2 enterprise if crypto['type'] in ('wpa', 'wpa2'): - # TODO: WPA2 enterprise - self._cfg['BASE']['Security'] = 'wpa' - # if crypto['type'] in ('wep', 'wpa', 'wpa2', 'wpa3'): - if crypto['type'] in ('wpa', 'wpa2'): - self._cfg['BASE']['Key'] = crypto['auth']['psk'] + self._wpasupp['psk'] = crypto['auth']['psk'] + else: + self._wpasupp['key_mgmt'] = 'NONE' + self.wpasupp_tpl = self.j2_env.get_template('wpa_supplicant.conf.j2') + self.services[('/usr/lib/systemd/system/wpa_supplicant@.service')] = ('etc/systemd/' + 'system/' + 'multi-user.target.wants/' + 'wpa_supplicant@' + '{0}.service').format(self.device) return() def _writeConnCfg(self, chroot_base): cfgroot = os.path.join(chroot_base, 'etc', 'wpa_supplicant') - cfgbase = os.path.join(cfgroot, 'wpa_supplicant.conf') - cfgfile = os.path.join(cfgroot, self.id) + cfgfile = os.path.join(cfgroot, 'wpa_supplicant-{0}.conf'.format(self.device)) + os.makedirs(cfgroot, exist_ok = True) + os.chown(cfgroot, 0, 0) + os.chmod(cfgroot, 0o0755) + with open(cfgfile, 'w') as fh: + fh.write(self.wpasupp_tpl.render(wpa = self._wpasupp)) + os.chown(cfgfile, 0, 0) + os.chmod(cfgfile, 0o0640) + return() diff --git a/aif/network/wpa_supplicant.conf.j2 b/aif/network/wpa_supplicant.conf.j2 new file mode 100644 index 0000000..5d70385 --- /dev/null +++ b/aif/network/wpa_supplicant.conf.j2 @@ -0,0 +1,9 @@ +# Generated by AIF-NG. +ctrl_interface=/run/wpa_supplicant +update_config=1 + +network={ +{%- for k, v in wpa.items() %} + {{ k }}={{ v }} +{%- endfor %} +} diff --git a/examples/aif.xml b/examples/aif.xml index cf5f5dd..6bbfd30 100644 --- a/examples/aif.xml +++ b/examples/aif.xml @@ -150,12 +150,15 @@ - + wpa2 - personal - ABadWiFiPassword + + ABadWiFiPassword + + +