From bb68fcc5ab280623651b31953e149d364d3f7bf9 Mon Sep 17 00:00:00 2001 From: Sergey Matveev <stargrave@stargrave.org> Date: Mon, 22 Aug 2022 17:18:25 +0300 Subject: [PATCH] Move to Tcl --- README | 54 +++++++++++---------- cryptoparty.ru.tcl | 3 ++ cryptoparty.ru.zsh | 3 -- default.zone.do | 10 ++-- nncpgo.org.tcl | 5 ++ nncpgo.org.zsh | 5 -- rc.tcl | 116 +++++++++++++++++++++++++++++++++++++++++++++ rc.zsh | 105 ---------------------------------------- 8 files changed, 159 insertions(+), 142 deletions(-) create mode 100644 cryptoparty.ru.tcl delete mode 100644 cryptoparty.ru.zsh create mode 100644 nncpgo.org.tcl delete mode 100644 nncpgo.org.zsh create mode 100644 rc.tcl delete mode 100644 rc.zsh diff --git a/README b/README index 065a8e4..2bc8414 100644 --- a/README +++ b/README @@ -1,38 +1,41 @@ zdns -- DNS zones creator helper -This is very simple zsh-based helper functions to create DNS zones. +This is very simple Tcl-based helper functions to create DNS zones. Many things are hardcoded there. Basically you just write ordinary -zsh script, sourcing the rc.zsh, containing various helper functions. +Tcl script, sourcing the rc.tcl, containing various helper functions. It expects DOMAIN variable to be set. +Initially that utility was written on zsh, but later it was replaced +with Tcl. + * fqdn(domain) -- prints fully-qualified domain name, taking either "domain.", or "@", or "subdomain" names -* shortened(domain) -- prints $DOMAIN-relative shortened name, printing +* shorten(domain) -- prints $DOMAIN-relative shortened name, printing only subdomain parts or "@" -* zone_start(serial) -- prints SOA record with two predefined (hardcoded) +* zone(serial) -- prints SOA record with two predefined (hardcoded) nameservers and none DMARC policy -* add_mx(domain) -- add predefined MX records for given domain, with +* mx(domain) -- add predefined MX records for given domain, with predefined redirect-based SPF policy -* add_dane(domain) -- add DANE records for given domain. You have to - have tls/ subdirectory, containing zeasypki's state +* dane(domain, [port=443]) -- add DANE records for given domain. You + have to have tls/ subdirectory, containing zeasypki's state (http://www.git.stargrave.org/?p=zeasypki.git;a=blob;f=README) It looks in each CA's subdirectory if keypair exists for the domain, printing necessary CAA and TLSA records -* add_ssh(domain) -- searches for corresponding public key in ssh/ +* ssh(domain) -- searches for corresponding public key in ssh/ subdirectory and (if it exists) prints corresponding SSHFP record -* add_subdomain(domain, addresses) -- adds specified domain with - provided space-separated addresses. It automatically calls add_dane - and add_ssh helpers. Unless $NOSPF=1 is specified, it prints "-all" - SPF policy. If $Y=1 is specified, then it adds "y.domain" address with - predefined $Y6 address and "-all" SPF policy -* add_pgp(keyid, uid) -- prints _openpgpkey DANE record for given - OpenPGP key of desired UID. "uid" is optional and useful only if your - key have got multiple UIDs and you need to add only the single - specified one +* subdomain(domain, addrs, [y nospf dane:PORT]) -- adds specified domain + with provided space-separated addresses. It automatically calls dane + and ssh helpers. Third argument is a list containing three optional + elements. Unless "nospf" is specified, it prints "-all" SPF policy. If + "y" is specified, it adds "y.domain" address with predefined $Y6 + address and "-all" SPF policy +* pgp(keyid, uid) -- prints _openpgpkey DANE record for given OpenPGP + key of desired UID. "uid" is optional and useful only if your key have + got multiple UIDs and you need to add only the single specified one -To omit burden of sourcing rc.zsh, setting $DOMAIN and rebuilding zones +To omit burden of sourcing rc.tcl, setting $DOMAIN and rebuilding zones after its change, there is default.zone.do redo (http://cr.yp.to/redo.html) -target, expecting your script in $domain.zsh file. +target, expecting your script in $domain.tcl file. For example the zone for nncpgo.org domain with mail-capabilities, WWW subdomain (available via Yggdrasil network), OpenPGP DANE key, @@ -48,12 +51,12 @@ created the following way: $ mkdir -p ssh $ print ssh-ed25519 AAAA... > ssh/www.nncpgo.org - $ cat > nncpgo.org.zsh <<EOF - zone_start 2012011633 - add_mx @ - Y=1 add_subdomain www "$GW4 $GW6 $VPS4 $VPS6" - Y=1 add_subdomain openpgpkey "$GW4 $GW6" - add_pgp releases@nncpgo.org + $ cat > nncpgo.org.tcl <<EOF + zone 2012011633 + mx @ + subdomain www "$GW4 $GW6 $VPS4 $VPS6" y + subdomain openpgpkey "$GW4 $GW6" y + pgp releases@nncpgo.org EOF $ redo nncpgo.org.zone @@ -84,6 +87,7 @@ It will produce: _443._tcp.www TLSA 3 1 1 0a77...d187 www CAA 0 issue "cagost.cypherpunks.ru" _443._tcp.www TLSA 3 1 1 9b98...7b3a + www SSHFP 4 2 e72b...c53f www TXT "v=spf1 -all" y.www AAAA 21a:af91:8d0e:b05:9645:e4e9:12be:3c39 y.www TXT "v=spf1 -all" diff --git a/cryptoparty.ru.tcl b/cryptoparty.ru.tcl new file mode 100644 index 0000000..ffbf749 --- /dev/null +++ b/cryptoparty.ru.tcl @@ -0,0 +1,3 @@ +zone 2012011623 +mx @ +subdomain @ "$GW4 $GW6 $VPS4 $VPS6" {y nospf} diff --git a/cryptoparty.ru.zsh b/cryptoparty.ru.zsh deleted file mode 100644 index 0a73562..0000000 --- a/cryptoparty.ru.zsh +++ /dev/null @@ -1,3 +0,0 @@ -zone_start 2012011622 -add_mx @ -Y=1 NOSPF=1 add_subdomain @ "$GW4 $GW6 $VPS4 $VPS6" diff --git a/default.zone.do b/default.zone.do index 73191d8..56501a9 100644 --- a/default.zone.do +++ b/default.zone.do @@ -1,4 +1,6 @@ -export DOMAIN=$2 -src="rc.zsh $2.zsh" -redo-ifchange $src -cat $src | zsh -e +redo-ifchange rc.tcl $2.tcl +PATH="$HOME/work/zeasypki:$PATH" tclsh8.6 <<EOF +set DOMAIN $2 +source rc.tcl +source $2.tcl +EOF diff --git a/nncpgo.org.tcl b/nncpgo.org.tcl new file mode 100644 index 0000000..7235a7a --- /dev/null +++ b/nncpgo.org.tcl @@ -0,0 +1,5 @@ +zone 2012011634 +mx @ +subdomain www "$GW4 $GW6 $VPS4 $VPS6" y +subdomain openpgpkey "$GW4 $GW6" y +pgp releases@nncpgo.org diff --git a/nncpgo.org.zsh b/nncpgo.org.zsh deleted file mode 100644 index 2b4f717..0000000 --- a/nncpgo.org.zsh +++ /dev/null @@ -1,5 +0,0 @@ -zone_start 2012011633 -add_mx @ -Y=1 add_subdomain www "$GW4 $GW6 $VPS4 $VPS6" -Y=1 add_subdomain openpgpkey "$GW4 $GW6" -add_pgp releases@nncpgo.org diff --git a/rc.tcl b/rc.tcl new file mode 100644 index 0000000..3df63dd --- /dev/null +++ b/rc.tcl @@ -0,0 +1,116 @@ +set GW4 91.211.5.21 +set GW6 2a03:e2c0:2663:1::1 + +set VPS4 45.10.110.72 +set VPS6 2a04:ac00:a:146::25 + +set Y6 21a:af91:8d0e:b05:9645:e4e9:12be:3c39 + +set NS1 uz544mqwggqbf3z4utlhfqn45vpbpq78nc63hpg5u2ut29stkt0pkr.ns7.stargrave.org. +set NS2 uz5nulnd504gp3s7sdmdl5l2gxc762hpw926t90k39ltxp67flbccn.ns5.stargrave.org. + +set NoSPF {"v=spf1 -all"} +set ReSPF {"v=spf1 redirect=_spf.stargrave.org"} + +proc zone {serial} { + global DOMAIN NS1 NS2 +puts "\$TTL 21600 +\$ORIGIN $DOMAIN. +$DOMAIN. 21600 IN SOA $NS1 admin.$DOMAIN. ( + $serial ; Serial + 12h ; Refresh + 2h ; Retry + 2w ; Expire + 6h ; TTL +) +@ NS $NS1 +@ NS $NS2 +_dmarc TXT \"v=DMARC1; p=none\"" +} + +proc fqdn {dn} { + global DOMAIN + switch -glob -- $dn { + @ { return $DOMAIN. } + *. { return $dn } + * { return $dn.$DOMAIN. } + } +} + +proc shorten {dn} { + set dn [fqdn $dn] + global DOMAIN + if { $dn == "$DOMAIN." } { return @ } + return [join [lrange [split $dn .] 0 end-[expr [llength [split $DOMAIN .]] + 1]] .] +} + +proc mx {dn} { + set dn [shorten $dn] + global ReSPF + puts "$dn MX 10 mailfake0.stargrave.org." + puts "$dn MX 20 mail2.stargrave.org." + puts "$dn MX 30 mailfake1.stargrave.org." + puts "$dn TXT $ReSPF" +} + +proc dane {dn {port ""}} { + set dn [fqdn $dn] + if {$port == ""} { set port 443 } + set dirname [string trimright $dn .] + set was [pwd] + cd tls + foreach ca [lsort [glob ca/*/*]] { + set ca [join [lrange [split $ca /] 1 end] /] + if {![file exists [file join ee $ca $dirname]]} { continue } + puts "[shorten $dn] CAA 0 issue \"[lindex [split $ca /] end]\"" + puts "[shorten _$port._tcp.$dn] TLSA 3 1 1 [exec zeasypki dane ee/$ca/$dirname]" + } + cd $was +} + +proc ssh {dn} { + set dn [fqdn $dn] + set fn ssh/[string trimright $dn .] + if {![file exists $fn]} { return } + set fd [open "| ssh-keygen -f $fn -r $dn"] + while {[gets $fd line] >= 0} { + if {[string first "SSHFP 4 2" $line] == -1} { continue } + puts "[shorten $dn] [lrange [split $line " "] 2 end]" + } + close $fd +} + +proc subdomain {dn addrs {flags {}}} { + global Y6 NoSPF + set short [shorten $dn] + foreach addr $addrs { + if {[string first : $addr] == -1} { set atyp A } { set atyp AAAA } + puts "$short $atyp $addr" + } + dane $dn [lindex [split [lindex $flags [lsearch $flags dane:*]] :] end] + ssh $dn + if {[lsearch $flags nospf] == -1} { puts "$short TXT $NoSPF" } + if {[lsearch $flags y] != -1} { + set short [shorten y.[fqdn $dn]] + puts "$short AAAA $Y6" + puts "$short TXT $NoSPF" + ssh $short + } +} + +proc pgp {keyid {uid ""}} { + if {$uid == ""} { set uid $keyid } + set fd [open "| gpg --export-options export-dane --export $keyid"] + while {[gets $fd line] >= 0} { + if {[string first $uid $line] != -1} { break } + } + puts $line + set line [split [gets $fd]] + set line [lreplace $line 0 0 "[lindex $line 0]._openpgpkey"] + puts [join $line] + while {[gets $fd line] >= 0} { + if {$line == ""} { break } + puts $line + } + catch {close $fd} +} diff --git a/rc.zsh b/rc.zsh deleted file mode 100644 index b3e32a6..0000000 --- a/rc.zsh +++ /dev/null @@ -1,105 +0,0 @@ -path=(~/work/zeasypki $path) - -NoSPF='"v=spf1 -all"' -ReSPF='"v=spf1 redirect=_spf.stargrave.org"' - -GW4=91.211.5.21 -GW6=2a03:e2c0:2663:1::1 -VPS4=45.10.110.72 -VPS6=2a04:ac00:a:146::25 -Y6=21a:af91:8d0e:b05:9645:e4e9:12be:3c39 - -NS1=uz544mqwggqbf3z4utlhfqn45vpbpq78nc63hpg5u2ut29stkt0pkr.ns7.stargrave.org. -NS2=uz5nulnd504gp3s7sdmdl5l2gxc762hpw926t90k39ltxp67flbccn.ns5.stargrave.org. - -zone_start() { - local serial=$1 - cat <<EOF -\$TTL 21600 -\$ORIGIN ${DOMAIN}. -${DOMAIN}. 21600 IN SOA $NS1 admin.${DOMAIN}. ( - ${serial} ; Serial - 12h ; Refresh - 2h ; Retry - 2w ; Expire - 6h ; TTL -) -@ NS $NS1 -@ NS $NS2 -_dmarc TXT "v=DMARC1; p=none" -EOF -} - -fqdn() { - case $1 in - @) print ${DOMAIN}. ;; - *.) print $1 ;; - *) print $1.${DOMAIN}. ;; - esac -} - -shortened() { - local dn=`fqdn $1` - case $dn in - ${DOMAIN}.) print @ ;; - *) print ${dn%%.${DOMAIN}.} ;; - esac -} - -add_mx() { - local shorten=`shortened $1` - cat <<EOF -$shorten MX 10 mailfake0.stargrave.org. -$shorten MX 20 mail2.stargrave.org. -$shorten MX 30 mailfake1.stargrave.org. -$shorten TXT $ReSPF -EOF -} - -add_dane() { - local domain=`fqdn $1` - local dirname=${domain%%.} - pushd tls - for ca (ca/*/*(on)) { - ca=(${(s#/#)ca}) - ca=${(j:/:)ca[2,-1]} - [[ -d ee/$ca/$dirname ]] || continue - print "`shortened $domain` CAA 0 issue \"${ca:t}\"" - print "`shortened _${DANE_PORT:-443}._tcp.$domain` TLSA 3 1 1 `zeasypki dane ee/$ca/$dirname`" - } - popd -} - -add_ssh() { - local domain=`fqdn $1` - local fn=ssh/${domain%%.} - [[ -r $fn ]] || return 0 - print "`shortened $1` SSHFP 4 2 `ssh-keygen -f $fn -r $domain | - sed -n 's/^.*SSHFP 4 2 \(.*\)$/\1/p'`" -} - -add_subdomain() { - local shorten=`shortened $1` - local atyp - for addr (${=2}) { - [[ $addr =~ : ]] && atyp=AAAA || atyp=A - print "$shorten $atyp $addr" - } - add_dane $1 - [[ -n $NOSPF ]] || print "$shorten TXT $NoSPF" - [[ -z $Y ]] || { - shorten=$(shortened y.$(fqdn $1)) - print "$shorten AAAA $Y6" - print "$shorten TXT $NoSPF" - add_ssh $shorten - } - add_ssh $1 -} - -add_pgp() { - local what=$2 - [[ -n "$what" ]] || what=$1 - what=${what:s/@/./} - gpg --export-options export-dane --export $1 | - perl -ne "next unless /${what}/../^$/ ; s/ TYPE61/._openpgpkey TYPE61/ ; print" -} -- 2.51.0