From 577962e09b55e44ba66a0e3f46d43043b4eb921c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauri=20V=C3=B5sandi?= Date: Mon, 9 Apr 2018 13:08:12 +0000 Subject: [PATCH] Several improvements * Add EC support * Make token form toggleable * Make client certificates compatible with iOS native IKEv2 * Fix OU for self-enroll * Improved sample scripts in web UI --- certidude/api/__init__.py | 10 +- certidude/api/token.py | 3 +- certidude/authority.py | 12 +- certidude/cli.py | 24 +- certidude/config.py | 3 + certidude/const.py | 2 + certidude/static/views/authority.html | 267 ++++++++++++++----- certidude/user.py | 2 +- doc/overlay/etc/hotplug.d/iface/50-certidude | 37 +-- doc/overlay/etc/profile | 11 +- doc/overlay/etc/uci-defaults/50-access-point | 66 ----- 11 files changed, 253 insertions(+), 184 deletions(-) mode change 100644 => 100755 doc/overlay/etc/hotplug.d/iface/50-certidude delete mode 100644 doc/overlay/etc/uci-defaults/50-access-point diff --git a/certidude/api/__init__.py b/certidude/api/__init__.py index 9d657d9..d74de32 100644 --- a/certidude/api/__init__.py +++ b/certidude/api/__init__.py @@ -10,7 +10,7 @@ from xattr import listxattr, getxattr from certidude.auth import login_required from certidude.user import User from certidude.decorators import serialize, csrf_protection -from certidude import const, config +from certidude import const, config, authority from .utils import AuthorityHandler logger = logging.getLogger(__name__) @@ -140,8 +140,11 @@ class SessionResource(AuthorityHandler): offline = 600, # Seconds from last seen activity to consider lease offline, OpenVPN reneg-sec option dead = 604800 # Seconds from last activity to consider lease dead, X509 chain broken or machine discarded ), - common_name = const.FQDN, - title = self.authority.certificate.subject.native["common_name"], + certificate = dict( + algorithm = authority.public_key.algorithm, + common_name = self.authority.certificate.subject.native["common_name"], + blob = self.authority.certificate_buf.decode("ascii"), + ), mailer = dict( name = config.MAILER_NAME, address = config.MAILER_ADDRESS @@ -164,6 +167,7 @@ class SessionResource(AuthorityHandler): ) ) if req.context.get("user").is_admin() else None, features=dict( + token=bool(config.TOKEN_URL), tagging=True, leases=True, logging=config.LOGGING_BACKEND)) diff --git a/certidude/api/token.py b/certidude/api/token.py index 1cc40f5..6d94b42 100644 --- a/certidude/api/token.py +++ b/certidude/api/token.py @@ -41,7 +41,8 @@ class TokenResource(AuthorityHandler): common_name = csr["certification_request_info"]["subject"].native["common_name"] assert common_name == username or common_name.startswith(username + "@"), "Invalid common name %s" % common_name try: - _, resp.body = self.authority._sign(csr, body, profile="default") + _, resp.body = self.authority._sign(csr, body, profile="default", + overwrite=config.TOKEN_OVERWRITE_PERMITTED) resp.set_header("Content-Type", "application/x-pem-file") logger.info("Autosigned %s as proven by token ownership", common_name) except FileExistsError: diff --git a/certidude/authority.py b/certidude/authority.py index 52a4859..f04ac0f 100644 --- a/certidude/authority.py +++ b/certidude/authority.py @@ -47,11 +47,16 @@ def self_enroll(): try: path, buf, cert, signed, expires = get_signed(common_name) - public_key = asymmetric.load_public_key(path) + self_public_key = asymmetric.load_public_key(path) private_key = asymmetric.load_private_key(self_key_path) except FileNotFoundError: # certificate or private key not found with open(self_key_path, 'wb') as fh: - public_key, private_key = asymmetric.generate_pair('rsa', bit_size=2048) + if public_key.algorithm == "ec": + self_public_key, private_key = asymmetric.generate_pair("ec", curve=public_key.curve) + elif public_key.algorithm == "rsa": + self_public_key, private_key = asymmetric.generate_pair("rsa", bit_size=public_key.bit_size) + else: + NotImplemented fh.write(asymmetric.dump_private_key(private_key, None)) else: now = datetime.utcnow() @@ -59,7 +64,7 @@ def self_enroll(): click.echo("Certificate %s still valid, delete to self-enroll again" % path) return - builder = CSRBuilder({"common_name": common_name}, public_key) + builder = CSRBuilder({"common_name": common_name}, self_public_key) request = builder.build(private_key) with open(os.path.join(directory, "requests", common_name + ".pem"), "wb") as fh: fh.write(pem_armor_csr(request)) @@ -389,6 +394,7 @@ def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, profile builder.subject_alt_domains = [common_name] # OpenVPN uses CN while StrongSwan uses SAN to match hostname of the server builder.extended_key_usage = set(["server_auth", "1.3.6.1.5.5.8.2.2", "client_auth"]) else: + builder.subject_alt_domains = [common_name] # iOS demands SAN also for clients builder.extended_key_usage = set(["client_auth"]) end_entity_cert = builder.build(private_key) diff --git a/certidude/cli.py b/certidude/cli.py index 2fae86c..18c6ce8 100755 --- a/certidude/cli.py +++ b/certidude/cli.py @@ -287,7 +287,17 @@ def certidude_enroll(fork, renew, no_wait, kerberos, skip_self): if not os.path.exists(request_path): key_partial = key_path + ".part" request_partial = request_path + ".part" - public_key, private_key = asymmetric.generate_pair('rsa', bit_size=2048) + + certificate = x509.Certificate.load(certificate_der_bytes) + public_key = asymmetric.load_public_key(certificate["tbs_certificate"]["subject_public_key_info"]) + + if public_key.algorithm == "ec": + self_public_key, private_key = asymmetric.generate_pair("ec", curve=public_key.curve) + elif public_key.algorithm == "rsa": + self_public_key, private_key = asymmetric.generate_pair("rsa", bit_size=public_key.bit_size) + else: + NotImplemented + builder = CSRBuilder({"common_name": common_name}, public_key) request = builder.build(private_key) with open(key_partial, 'wb') as f: @@ -945,8 +955,9 @@ def certidude_setup_openvpn_networkmanager(authority, remote, common_name, **pat @click.option("--server-flags", is_flag=True, help="Add TLS Server and IKE Intermediate extended key usage flags") @click.option("--outbox", default="smtp://smtp.%s" % const.DOMAIN, help="SMTP server, smtp://smtp.%s by default" % const.DOMAIN) @click.option("--skip-packages", is_flag=True, help="Don't attempt to install apt/pip/npm packages") +@click.option("--elliptic-curve", "-e", is_flag=True, help="Generate EC instead of RSA keypair") @fqdn_required -def certidude_setup_authority(username, kerberos_keytab, nginx_config, country, state, locality, organization, organizational_unit, common_name, directory, authority_lifetime, push_server, outbox, server_flags, title, skip_packages): +def certidude_setup_authority(username, kerberos_keytab, nginx_config, country, state, locality, organization, organizational_unit, common_name, directory, authority_lifetime, push_server, outbox, server_flags, title, skip_packages, elliptic_curve): assert os.getuid() == 0 and os.getgid() == 0, "Authority can be set up only by root" import pwd @@ -1160,9 +1171,12 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, country, # Generate and sign CA key if not os.path.exists(ca_key): - click.echo("Generating %d-bit RSA key for CA ..." % const.KEY_SIZE) - - public_key, private_key = asymmetric.generate_pair('rsa', bit_size=const.KEY_SIZE) + if elliptic_curve: + click.echo("Generating %s EC key for CA ..." % const.CURVE_NAME) + public_key, private_key = asymmetric.generate_pair("ec", curve=const.CURVE_NAME) + else: + click.echo("Generating %d-bit RSA key for CA ..." % const.KEY_SIZE) + public_key, private_key = asymmetric.generate_pair("rsa", bit_size=const.KEY_SIZE) names = ( ("country_name", country), diff --git a/certidude/config.py b/certidude/config.py index 2ef6785..e33aa85 100644 --- a/certidude/config.py +++ b/certidude/config.py @@ -99,3 +99,6 @@ PROFILES = OrderedDict([[i, [j.strip() for j in cp.get("profile", i).split(",")] cp2 = configparser.RawConfigParser() cp2.readfp(open(const.BUILDER_CONFIG_PATH, "r")) IMAGE_BUILDER_PROFILES = [(j, cp2.get(j, "title"), cp2.get(j, "rename")) for j in cp2.sections()] + + +TOKEN_OVERWRITE_PERMITTED=True diff --git a/certidude/const.py b/certidude/const.py index 2e406e9..1480c8d 100644 --- a/certidude/const.py +++ b/certidude/const.py @@ -5,6 +5,8 @@ import socket import sys KEY_SIZE = 1024 if os.getenv("TRAVIS") else 4096 +CURVE_NAME = "secp384r1" + RUN_DIR = "/run/certidude" CONFIG_DIR = "/etc/certidude" SERVER_CONFIG_PATH = os.path.join(CONFIG_DIR, "server.conf") diff --git a/certidude/static/views/authority.html b/certidude/static/views/authority.html index f9b2be6..057241c 100644 --- a/certidude/static/views/authority.html +++ b/certidude/static/views/authority.html @@ -13,7 +13,7 @@
easy_install pip;
 pip3 install certidude;
-certidude bootstrap {{session.authority.common_name}}
+certidude bootstrap {{ window.location.hostname }}
   
@@ -30,14 +30,16 @@ Signature="$Windows NT$ [NewRequest] Subject = "CN=$hostname" Exportable = FALSE -KeyLength = 2048 KeySpec = 1 KeyUsage = 0xA0 MachineKeySet = True -ProviderName = "Microsoft RSA SChannel Cryptographic Provider" ProviderType = 12 RequestType = PKCS10 -"@ +{% if session.authority.certificate.algorithm == "ec" %}ProviderName = "Microsoft Software Key Storage Provider" +KeyAlgorithm = ECDSA_P384 +{% else %}ProviderName = "Microsoft RSA SChannel Cryptographic Provider" +KeyLength = 2048 +{% endif %}"@ $templ | Out-File req.inf @@ -54,8 +56,23 @@ Import-Certificate -FilePath client_cert.pem -CertStoreLocation Cert:\LocalMachi # Set up IPSec VPN tunnel Remove-VpnConnection -AllUserConnection -Force k-space -Add-VpnConnection -Name k-space -ServerAddress guests.k-space.ee -SplitTunneling -PassThru -TunnelType ikev2 -AllUserConnection -AuthenticationMethod MachineCertificate -Set-VpnConnectionIPsecConfiguration -ConnectionName k-space -AuthenticationTransformConstants SHA256128 -CipherTransformConstants AES256 -EncryptionMethod AES256 -IntegrityCheckMethod SHA384 -PfsGroup PFS24 -DHGroup Group24 -PassThru -AllUserConnection -Force +Add-VpnConnection ` + -Name k-space ` + -ServerAddress guests.k-space.ee ` + -AuthenticationMethod MachineCertificate ` + -SplitTunneling ` + -TunnelType ikev2 ` + -PassThru -AllUserConnection + +# Security hardening +Set-VpnConnectionIPsecConfiguration ` + -ConnectionName k-space ` + -AuthenticationTransformConstants GCMAES128 ` + -CipherTransformConstants GCMAES128 ` + -EncryptionMethod AES128 ` + -IntegrityCheckMethod none ` + -PfsGroup {% if session.authority.certificate.algorithm == "ec" %}ECP384 -DHGroup ECP384{% else %}PFS2048 -DHGroup Group14{% endif %} ` + -PassThru -AllUserConnection -Force
UNIX & UNIX-like
@@ -63,58 +80,110 @@ Set-VpnConnectionIPsecConfiguration -ConnectionName k-space -AuthenticationTrans

On other UNIX-like machines generate key pair and submit the signing request using OpenSSL and cURL:

NAME=$(hostname);
-openssl genrsa -out client_key.pem 2048;
-openssl req -new -sha256 -key client_key.pem -out client_req.pem -subj "/CN=$NAME";
+{% if session.authority.certificate.algorithm == "ec" %}openssl ecparam -name secp384r1 -genkey -noout -out client_key.pem{% else %}openssl genrsa -out client_key.pem 2048;{% endif %}
+openssl req -new -sha384 -key client_key.pem -out client_req.pem -subj "/CN=$NAME";
 curl -f -L -H "Content-type: application/pkcs10" --data-binary @client_req.pem \
   http://{{ window.location.hostname }}/api/request/?wait=yes > client_cert.pem
-
OpenVPN gateway on OpenWrt/LEDE router
+
StrongSwan as client
+ +

First enroll certificates:

+
+

+FQDN=$(cat /etc/hostname)
+curl -f http://{{ window.location.hostname }}/api/certificate/ -o /etc/ipsec.d/cacerts/ca.pem; \
+test -e /etc/ipsec.d/private/client.pem \
+ || openssl ecparam -name secp384r1 -genkey -noout -out /etc/ipsec.d/private/client.pem; \
+test -e /etc/ipsec.d/reqs/client.pem \
+ || openssl req -new -sha384 \
+      -key /etc/ipsec.d/private/client.pem \
+      -out /etc/ipsec.d/reqs/client.pem -subj "/CN=$FQDN"; \
+curl -f -L -H "Content-type: application/pkcs10" \
+  --data-binary @/etc/ipsec.d/reqs/client.pem \
+  -o /etc/ipsec.d/certs/client.pem \
+  http://{{ window.location.hostname }}/api/request/?wait=yes
+
+ +

Then configure StrongSwan

+
+

+cat > /etc/ipsec.conf << EOF
+conn c2s
+    auto=start
+    right=router.k-space.ee
+    dpdaction=restart
+    closeaction=restart
+    left=%defaultroute
+    rightsubnet=0.0.0.0/0
+    keyingtries=%forever
+    rightid=%any
+    leftsourceip=%config
+    leftcert=client.pem
+    ike=aes128-sha384-{% if session.authority.certificate.algorithm == "ec" %}ecp384{% else %}modp2048{% endif %}!
+    esp=aes128gcm16!
+
+EOF
+
+echo ": {% if session.authority.certificate.algorithm == "ec" %}ECDSA{% else %}RSA{% endif %} client.pem" > /etc/ipsec.secrets
+
+ipsec restart
+
+ +
OpenWrt/LEDE as VPN gateway

First enroll certificates:

# Derive FQDN from WAN interface's reverse DNS record
 FQDN=$(nslookup $(uci get network.wan.ipaddr) |  grep "name =" | head -n1 | cut -d "=" -f 2 | xargs)
 
-mkdir -p /etc/certidude/authority/{{ window.location.hostname }}; \
-grep -c certidude /etc/sysupgrade.conf || echo /etc/certidude >> /etc/sysupgrade.conf; \
-curl -f http://{{ window.location.hostname }}/api/certificate/ -o /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem; \
+mkdir -p /etc/certidude/authority/{{ window.location.hostname }}
+grep -c certidude /etc/sysupgrade.conf || echo /etc/certidude >> /etc/sysupgrade.conf
+cat << EOF > /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem
+{{ session.authority.certificate.blob }}
+EOF
 test -e /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem \
- || openssl genrsa -out /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem 2048; \
+ || openssl {% if session.authority.certificate.algorithm == "ec" %}ecparam -name secp384r1 -genkey -noout -out /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem{% else %}genrsa -out /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem 2048{% endif %}
 test -e /etc/certidude/authority/{{ window.location.hostname }}/server_req.pem \
- || openssl req -new -sha256 \
+ || openssl req -new -sha384 \
       -key /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem \
-      -out /etc/certidude/authority/{{ window.location.hostname }}/server_req.pem -subj "/CN=$FQDN"; \
+      -out /etc/certidude/authority/{{ window.location.hostname }}/server_req.pem -subj "/CN=$FQDN"
+cat /etc/certidude/authority/{{ window.location.hostname }}/server_req.pem
 curl -f -L -H "Content-type: application/pkcs10" \
   --data-binary @/etc/certidude/authority/{{ window.location.hostname }}/server_req.pem \
   -o /etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem \
-  http://{{ window.location.hostname }}/api/request/?wait=yes
-
+ http://{{ window.location.hostname }}/api/request/?wait=yes -

Then set up service:

-
-
# Create VPN gateway up/down script for reporting client IP addresses to CA
-cat <<\EOF > /etc/certidude/updown
+# Create VPN gateway up/down script for reporting client IP addresses to CA
+cat <<\EOF > /etc/certidude/authority/{{ window.location.hostname }}/updown
 #!/bin/sh
-CURL="curl -f --key /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem --cert /etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem --cacert /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem https://{{ window.location.hostname }}:8443/api/lease/"
+
+CURL="curl -m 3 -f --key /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem --cert /etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem --cacert /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem https://{{ window.location.hostname }}:8443/api/lease/"
 
 case $PLUTO_VERB in
-  up-client|down-client) $CURL --data "outer_address=$PLUTO_PEER&inner_address=$PLUTO_PEER_SOURCEIP&client=$PLUTO_PEER_ID" ;;
-  *) $CURL --data "client=$X509_0_CN&outer_address=$untrusted_ip&inner_address=$ifconfig_pool_remote_ip&serial=$tls_serial_0" ;;
+  up-client) $CURL --data-urlencode "outer_address=$PLUTO_PEER" --data-urlencode "inner_address=$PLUTO_PEER_SOURCEIP" --data-urlencode "client=$PLUTO_PEER_ID" ;;
+  *) ;;
+esac
+
+case $script_type in
+  client-connect) $CURL --data-urlencode client=$X509_0_CN --data-urlencode serial=$tls_serial_0 --data-urlencode outer_address=$untrusted_ip --data-urlencode inner_address=$ifconfig_pool_remote_ip  ;;
+  *) ;;
 esac
 EOF
 
-chmod +x /etc/certidude/updown
+chmod +x /etc/certidude/authority/{{ window.location.hostname }}/updown
+
- -# Generate Diffie-Hellman parameters file for OpenVPN +

Then either set up OpenVPN service:

+
+
# Generate Diffie-Hellman parameters file for OpenVPN
 test -e /etc/certidude/dh.pem \
  || openssl dhparam 2048 -out /etc/certidude/dh.pem
 
 # Create interface definition for tunnel
 uci set network.vpn=interface
 uci set network.vpn.name='vpn'
-uci set network.vpn.ifname=tun_s2c
+uci set network.vpn.ifname=tun_s2c_udp tun_s2c_tcp
 uci set network.vpn.proto='none'
 
 # Create zone definition for VPN interface
@@ -133,6 +202,14 @@ uci set firewall.openvpn.dest_port=1194
 uci set firewall.openvpn.proto='udp'
 uci set firewall.openvpn.target='ACCEPT'
 
+# Allow TCP 443 on WAN interface
+uci set firewall.openvpn=rule
+uci set firewall.openvpn.name='Allow OpenVPN over TCP'
+uci set firewall.openvpn.src='wan'
+uci set firewall.openvpn.dest_port=443
+uci set firewall.openvpn.proto='tcp'
+uci set firewall.openvpn.target='ACCEPT'
+
 # Forward traffic from VPN to LAN
 uci set firewall.c2s=forwarding
 uci set firewall.c2s.src='vpn'
@@ -142,31 +219,83 @@ uci set firewall.c2s.dest='lan'
 uci set dhcp.@dnsmasq[0].localservice='0'
 
 touch /etc/config/openvpn
-uci set openvpn.s2c=openvpn
-uci set openvpn.s2c.local=$(uci get network.wan.ipaddr)
-uci set openvpn.s2c.script_security=2
-uci set openvpn.s2c.client_connect='/etc/certidude/updown'
-uci set openvpn.s2c.tls_version_min='1.2'
-uci set openvpn.s2c.tls_cipher='TLS-DHE-RSA-WITH-AES-256-GCM-SHA384'
-uci set openvpn.s2c.cipher='AES-256-CBC'
-uci set openvpn.s2c.auth='SHA384'
-uci set openvpn.s2c.dev=tun_s2c
-uci set openvpn.s2c.server='10.179.43.0 255.255.255.0'
-uci set openvpn.s2c.key='/etc/certidude/authority/{{ window.location.hostname }}/server_key.pem'
-uci set openvpn.s2c.cert='/etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem'
-uci set openvpn.s2c.ca='/etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem'
-uci set openvpn.s2c.dh='/etc/certidude/dh.pem'
-uci set openvpn.s2c.enabled=1
-uci set openvpn.s2c.comp_lzo=yes
-uci add_list openvpn.s2c.push="route-metric 1000"
-uci add_list openvpn.s2c.push="route $(uci get network.lan.ipaddr) $(uci get network.lan.netmask)"
-uci add_list openvpn.s2c.push="dhcp-option DNS $(uci get network.lan.ipaddr)"
-uci add_list openvpn.s2c.push="dhcp-option DOMAIN $(uci get dhcp.@dnsmasq[0].domain)"
+
+# Configure OpenVPN over TCP
+uci set openvpn.s2c_tcp=openvpn
+uci set openvpn.s2c_tcp.local=$(uci get network.wan.ipaddr)
+uci set openvpn.s2c_tcp.server='10.179.43.0 255.255.255.128'
+uci set openvpn.s2c_tcp.proto='tcp-server'
+uci set openvpn.s2c_tcp.port='443'
+uci set openvpn.s2c_tcp.dev=tun_s2c_tcp
+
+# Configure OpenVPN over UDP
+uci set openvpn.s2c_udp=openvpn
+uci set openvpn.s2c_udp.local=$(uci get network.wan.ipaddr)
+uci set openvpn.s2c_udp.server='10.179.43.128 255.255.255.128'
+uci set openvpn.s2c_tcp.dev=tun_s2c_udp
+
+for section in s2c_tcp s2c_udp; do
+
+# Common paths
+uci set openvpn.$section.script_security=2
+uci set openvpn.$section.client_connect='/etc/certidude/updown'
+uci set openvpn.$section.key='/etc/certidude/authority/{{ window.location.hostname }}/server_key.pem'
+uci set openvpn.$section.cert='/etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem'
+uci set openvpn.$section.ca='/etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem'
+uci set openvpn.$section.dh='/etc/certidude/dh.pem'
+uci set openvpn.$section.enabled=1
+
+# DNS and routes
+uci add_list openvpn.$section.push="route-metric 1000"
+uci add_list openvpn.$section.push="route $(uci get network.lan.ipaddr) $(uci get network.lan.netmask)"
+uci add_list openvpn.$section.push="dhcp-option DNS $(uci get network.lan.ipaddr)"
+uci add_list openvpn.$section.push="dhcp-option DOMAIN $(uci get dhcp.@dnsmasq[0].domain)"
+
+# Security hardening
+uci set openvpn.$section.tls_version_min='1.2'
+uci set openvpn.$section.tls_cipher='TLS-{% if session.authority.certificate.algorithm == "ec" %}ECDHE-ECDSA{% else %}DHE-RSA{% endif %}-WITH-AES-128-GCM-SHA384'
+uci set openvpn.$section.cipher='AES-128-GCM'
+uci set openvpn.$section.auth='SHA384'
+
+done
 
 /etc/init.d/openvpn restart
 /etc/init.d/firewall restart
+

Alternatively or additionally set up StrongSwan:

+
+
# Generate StrongSwan config
+cat > /etc/ipsec.conf << EOF
+config setup
+    strictcrlpolicy=yes
+    uniqueids = yes
+
+ca {{ window.location.hostname }}
+    auto=add
+    cacert = /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem
+    crluri = http://{{ window.location.hostname }}/api/revoked
+    ocspuri = http://{{ window.location.hostname }}/api/ocsp/
+
+conn s2c
+    auto=add
+    dpdaction=clear
+    closeaction=clear
+    leftdns=$(uci get network.lan.ipaddr)
+    rightsourceip=172.21.0.0/24
+    left=$(uci get network.wan.ipaddr)
+    leftsubnet=$(uci get network.lan.ipaddr | cut -d . -f 1-3).0/24
+    leftcert=/etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem
+    ike=aes128-sha384-{% if session.authority.certificate.algorithm == "ec" %}ecp384{% else %}modp2048{% endif %}!
+    esp=aes128gcm16!
+    leftupdown=/etc/certidude/{{ window.location.hostname }}/updown
+
+EOF
+
+echo ": {% if session.authority.certificate.algorithm == "ec" %}ECDSA{% else %}RSA{% endif %} /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem" > /etc/ipsec.secrets
+
+ipsec restart
+
{% if session.authority.builder %}
OpenWrt/LEDE image builder
@@ -337,28 +466,30 @@ forbidden
-

Tokens

- -

Tokens allow enrolling smartphones and third party devices.

- -

-

- - - - - -
-

- -
- {% if session.authority %} + {% if session.features.token %} +

Tokens

+ +

Tokens allow enrolling smartphones and third party devices.

+ +

+

+ + + + + +
+

+ +
+ {% endif %} +

Pending requests

Use Certidude client to apply for a certificate. diff --git a/certidude/user.py b/certidude/user.py index a95c5a2..a125a1e 100644 --- a/certidude/user.py +++ b/certidude/user.py @@ -39,7 +39,7 @@ class PosixUserManager(object): _, _, _, _, gecos, _, _ = pwd.getpwnam(username) gecos = gecos.split(",") full_name = gecos[0] - mail = "%s@%s" % (username, const.DOMAIN) + mail = "%s@%s" % ("tteearu", "k-space.ee") # username, "k-space.ee") # const.DOMAIN) if full_name and " " in full_name: given_name, surname = full_name.split(" ", 1) return User(username, mail, given_name, surname) diff --git a/doc/overlay/etc/hotplug.d/iface/50-certidude b/doc/overlay/etc/hotplug.d/iface/50-certidude old mode 100644 new mode 100755 index 7498784..0103a43 --- a/doc/overlay/etc/hotplug.d/iface/50-certidude +++ b/doc/overlay/etc/hotplug.d/iface/50-certidude @@ -5,12 +5,13 @@ # TODO: renewal +AUTHORITY=certidude.@authority[0] + [ $ACTION == "ifup" ] || exit 0 -[ $INTERFACE == "wan" ] || exit 0 +[ $INTERFACE == "$(uci get $AUTHORITY.trigger)" ] || exit 0 # TODO: iterate over all authorities -AUTHORITY=certidude.@authority[0] URL=$(uci get $AUTHORITY.url) GATEWAY=$(uci get $AUTHORITY.gateway) @@ -40,8 +41,9 @@ logger -t certidude -s "Time is now: $(date)" # If certificate file is there assume everything's set up if [ -f $CERTIFICATE_PATH ]; then SERIAL=$(openssl x509 -in $CERTIFICATE_PATH -noout -serial | cut -d "=" -f 2 | tr [A-F] [a-f]) - logger -t certidude -s "Certificate with serial $SERIAL already exists, attempting to bring up IPsec tunnel..." - ipsec up client-to-site + logger -t certidude -s "Certificate with serial $SERIAL already exists in $CERTIFICATE_PATH, attempting to bring up VPN tunnel..." + /etc/init.d/openvpn start + /etc/init.d/ipsec start exit 0 fi @@ -60,7 +62,7 @@ fi if [ ! -f $KEY_PATH ]; then KEY_TEMP=$(mktemp -u) - logger -t certidude -s "Generating RSA key for IPsec..." + logger -t certidude -s "Generating RSA key for VPN..." if [ -d $GREEN_LED ]; then echo 250 | tee $GREEN_LED/delay_* fi @@ -167,31 +169,10 @@ fi logger -t certidude -s "Certificate md5sum: $(md5sum -b $CERTIFICATE_TEMP)" - - - -################################### -### Generate /etc/ipsec.secrets ### -################################### - -SECRETS_TEMP=$(mktemp -u) - -for filename in /etc/ipsec.d/private/*.pem; do - echo ": RSA $filename" >> $SECRETS_TEMP -done - uci commit -mv $SECRETS_TEMP /etc/ipsec.secrets -mv $IPSEC_TEMP /etc/ipsec.conf mv $CERTIFICATE_TEMP $CERTIFICATE_PATH -# Enable services -/etc/init.d/ipsec enable - # Restart services -/etc/init.d/ipsec restart - -sleep 2 - -ipsec up client-to-site +/etc/init.d/ipsec start +/etc/init.d/openvpn start diff --git a/doc/overlay/etc/profile b/doc/overlay/etc/profile index 7203174..cda8b51 100644 --- a/doc/overlay/etc/profile +++ b/doc/overlay/etc/profile @@ -14,18 +14,11 @@ export PS1='\u@\h:\w\$ ' [ -x /usr/bin/ldd ] || ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; } HOSTNAME=$(uci get system.@system[0].hostname) -DOMAIN=$(uci -q get dhcp.@dnsmasq[0].domain) -if [ $? -eq 0 ]; then - FQDN=$HOSTNAME.$DOMAIN -else - FQDN=$HOSTNAME -fi - -export PS1='\[\033[01;31m\]$FQDN\[\033[01;34m\] \W #\[\033[00m\] ' +export PS1='\[\033[01;31m\]$HOSTNAME\[\033[01;34m\] \W #\[\033[00m\] ' case "$TERM" in xterm*|rxvt*) - echo -ne "\033]0;${USER}@${FQDN}:${PWD}\007" + echo -ne "\033]0;${USER}@${HOSTNAME}:${PWD}\007" ;; *) ;; diff --git a/doc/overlay/etc/uci-defaults/50-access-point b/doc/overlay/etc/uci-defaults/50-access-point deleted file mode 100644 index a57ad51..0000000 --- a/doc/overlay/etc/uci-defaults/50-access-point +++ /dev/null @@ -1,66 +0,0 @@ -# Disable DHCP servers -/etc/init.d/odhcpd disable -/etc/init.d/dnsmasq disable - -# Remove firewall rules since AP bridges ethernet to wireless anyway -uci delete firewall.@zone[1] -uci delete firewall.@zone[0] -uci delete firewall.@forwarding[0] -for j in $(seq 0 10); do uci delete firewall.@rule[0]; done - -# Remove WAN interface -uci delete network.wan -uci delete network.wan6 - -# Reconfigure DHCP client for bridge over LAN and WAN ports -uci delete network.lan.ipaddr -uci delete network.lan.netmask -uci delete network.lan.ip6assign -uci delete network.globals.ula_prefix -uci delete network.@switch_vlan[1] -uci delete dhcp.@dnsmasq[0].domain -uci set network.lan.proto=dhcp -uci set network.lan.ipv6=0 -uci set network.lan.ifname='eth0' -uci set network.lan.stp=1 - -# Radio ordering differs among models -case $(uci get wireless.radio0.hwmode) in - 11a) uci rename wireless.radio0=radio5ghz;; - 11g) uci rename wireless.radio0=radio2ghz;; -esac -case $(uci get wireless.radio1.hwmode) in - 11a) uci rename wireless.radio1=radio5ghz;; - 11g) uci rename wireless.radio1=radio2ghz;; -esac - -# Reset virtual SSID-s -uci delete wireless.@wifi-iface[1] -uci delete wireless.@wifi-iface[0] - -# Pseudorandomize channel selection, should work with 80MHz on 5GHz band -case $(uci get system.@system[0].hostname | md5sum) in - 1*|2*|3*|4*) uci set wireless.radio2ghz.channel=1; uci set wireless.radio5ghz.channel=36 ;; - 5*|6*|7*|8*) uci set wireless.radio2ghz.channel=5; uci set wireless.radio5ghz.channel=52 ;; - 9*|0*|a*|b*) uci set wireless.radio2ghz.channel=9; uci set wireless.radio5ghz.channel=100 ;; - c*|d*|e*|f*) uci set wireless.radio2ghz.channel=13; uci set wireless.radio5ghz.channel=132 ;; -esac - -# Create bridge for guests -uci set network.guest=interface -uci set network.guest.proto='static' -uci set network.guest.address='0.0.0.0' -uci set network.guest.type='bridge' -uci set network.guest.ifname='eth0.156' # tag id 156 for guest network -uci set network.guest.ipaddr='0.0.0.0' -uci set network.guest.ipv6=0 -uci set network.guest.stp=1 - -# Disable switch tagging and bridge all ports on TP-Link WDR3600/WDR4300 -case $(cat /etc/board.json | jsonfilter -e '@["model"]["id"]') in - tl-wdr*) - uci set network.@switch[0].enable_vlan=0 - uci set network.@switch_vlan[0].ports='0 1 2 3 4 5 6' - ;; - *) ;; -esac