Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] Completion: Add _ipsec, _swanctl
- X-seq: zsh-workers 43959
- From: dana <dana@xxxxxxx>
- To: Zsh workers <zsh-workers@xxxxxxx>
- Subject: [PATCH] Completion: Add _ipsec, _swanctl
- Date: Sun, 30 Dec 2018 17:14:37 -0600
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dana-is.20150623.gappssmtp.com; s=20150623; h=from:content-transfer-encoding:mime-version:subject:message-id:date :to; bh=pE50U1t53jFR5qbd8HXznTFtsU/oMe5TtaZHm7AybvI=; b=GSKVGAdnXGZ7qA10YzVvD9kL5GaTY4mYLPa6MWFESF2JBJVj5VnkZU+1a1Da6gbIZ0 Kn0LzhzLHybNNBrCSD8RjRfeSNSUS8z+j/UI4HTKqZcUB4Plq2erXrpfyIYIdQu4a88w M1KKsaZVSonuz+1HOF0TZW4v4yw7H/vtWKlbdG53HuQFWz0ZOWogRmF8BwxpkfMdWuG+ AjP26Ot+arela0yGh6F3xeaFMsxtLT05r/afTCw3CkU1X86Zcs6fYmQ6a68Oh7d73ObY lg85oePZ3yVqS1Y5Zz6PiJCIYkuU66gzcvsJkvSoEIIu3OjPa5y4WtpFw1CZNv9Fistd QtzA==
- List-help: <mailto:zsh-workers-help@zsh.org>
- List-id: Zsh Workers List <zsh-workers.zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- List-unsubscribe: <mailto:zsh-workers-unsubscribe@zsh.org>
- Mailing-list: contact zsh-workers-help@xxxxxxx; run by ezmlm
New functions for ipsec and swanctl (provided by strongSwan, &al.)
Also a very minor addition to _urls
(_swanctl is what led me to workers/43922 (handling of options like -+). I
haven't merged that yet because i found that it impacts the behaviour for some
already-broken edge-case options like -: and -\. Want to see how irritating
it'd be to fix those properly rather than just shuffle the brokenness around)
dana
diff --git a/Completion/Unix/Command/_ipsec b/Completion/Unix/Command/_ipsec
new file mode 100644
index 000000000..631d2bc9a
--- /dev/null
+++ b/Completion/Unix/Command/_ipsec
@@ -0,0 +1,179 @@
+#compdef ipsec strongswan
+
+# Completion for the ipsec script (aka strongswan on some systems) provided by
+# FreeS/WAN, Openswan, Libreswan, and strongSwan. See also strongSwan's swanctl.
+#
+# As with swanctl, elevated privileges are usually required to complete SA names
+# and the like; consider setting the gain-privileges style as follows:
+# zstyle ':completion:*:(ipsec|strongswan)/*' gain-privileges yes
+#
+# @todo We don't complete pool names or virtual IPs
+
+# Complete connection (IKE SA) names and optionally SA/instance names
+# --instances => also complete SA/instance names
+(( $+functions[_ipsec_connections] )) ||
+_ipsec_connections() {
+ local -a instances tmp ipsec_conns ipsec_insts
+
+ zparseopts -D -E -a instances - -instances
+
+ tmp=( ${(f)${"$(
+ _call_program -p ipsec-status ${_ipsec_cmd:-$words[1]} statusall
+ )"#*$'\n'[[:space:]]#[Cc]onnections:[[:space:]]#$'\n'}} )
+ tmp=( ${(@M)tmp:#[[:space:]]#[^[:space:]]##:[[:space:]]##?*} )
+ tmp=( ${(@)${(@)tmp##[[:space:]]##}%%:*} )
+
+ ipsec_conns=( ${(@)tmp%%['[{']<->['}]']} )
+ ipsec_insts=( ${(@M)tmp:#*['[{']<->['}]']} )
+
+ (( $#ipsec_conns )) || {
+ _message -e connections 'connection name'
+ return
+ }
+
+ tmp=( 'connections:connection name:compadd -a - ipsec_conns' )
+ (( $#instances && $#ipsec_insts )) &&
+ tmp+=( 'instances:connection SA/instance name:compadd -a - ipsec_insts' )
+
+ _alternative $tmp
+}
+
+# Complete arguments to /usr/lib/ipsec/starter. This is rarely invoked directly,
+# and there is almost no documentation on it, but the start/restart commands
+# pass options to it
+(( $+functions[_ipsec_starter] )) ||
+_ipsec_starter() {
+ _arguments : \
+ '(--nofork)--attach-gdb[start daemon under gdb (implies --nofork)]' \
+ '--auto-update[specify select time-out]:select time-out (seconds)' \
+ '--conf[specify path to ipsec.conf]:ipsec.conf file:_files' \
+ '--daemon[specify daemon name]:daemon name' \
+ '--nofork[do not fork daemon]' \
+ + '(d)' \
+ '--debug[set log level 2]' \
+ '--debug-more[set log level 3]' \
+ '--debug-all[set log level 4]' \
+ '--nolog[set log level 0]'
+}
+
+_ipsec() {
+ local ret=1 variant _ipsec_cmd=$words[1]
+ local -a context line state state_descr tmp
+ local -A opt_args
+
+ _pick_variant -r variant \
+ freeswan='(#i)frees/#wan' \
+ libreswan='(#i)libreswan' \
+ openswan='(#i)openswan' \
+ strongswan='(#i)strongswan' \
+ unix \
+ --version
+
+ # Provide only basic completion for non-strongSwan implementations
+ if [[ $variant == unix ]]; then
+ _default
+ return
+ elif [[ $variant == (free|libre|open)* ]]; then
+ tmp=( ${(f)"$( _call_program ipsec-help $words[1] --help )"} )
+ tmp=( ${(@M)tmp:#($' '|$'\t')*} )
+ tmp=( ${(@)tmp:#*[':/<>()[]']*} )
+ tmp=( ${(f)${(F)tmp//[[:space:]]##/$'\n'}} )
+
+ _arguments -S -A '-*' : \
+ '(: * -)--help[display help information]' \
+ '(: * -)--version[display version information]' \
+ "(-)1:command:(${(j< >)${(@q-)tmp}})" \
+ '(-)2: :_default'
+ return
+ fi
+
+ _arguments -A '-*' \
+ '(: * -)--confdir[display path to configuration directory (IPSEC_CONFDIR)]' \
+ '(: * -)--copyright[display copyright information]' \
+ '(: * -)--directory[display path to libexec/utility directory (IPSEC_DIR)]' \
+ '(: * -)--help[display help information]' \
+ '(: * -)--piddir[display path to PID directory (IPSEC_PIDDIR)]' \
+ '(: * -)--version[display version information]' \
+ '(: * -)--versioncode[display brief version information]' \
+ '1:command:((
+ down\:"terminate IPsec connection/SA"
+ down-srcip\:"terminate IKE SAs by client virtual IP"
+ leases\:"display IP address/pool status"
+ listaacerts\:"display X.509 authorization authority certificates"
+ listacerts\:"display X.509 attribute certificates"
+ listalgs\:"display loaded algorithms"
+ listall\:"execute all list commands"
+ listcacerts\:"display X.509 certificate authority certificates"
+ listcainfos\:"display certificate authority information"
+ listcerts\:"display X.509/OpenPGP certificates"
+ listcounters\:"display IKE counter information"
+ listcrls\:"display certificate revocation lists"
+ listgroups\:"display groups for user authorization profiles"
+ listocsp\:"display OCSP revocation information"
+ listocspcerts\:"display X.509 OCSP signer certificates"
+ listplugins\:"display loaded plug-in features"
+ listpubkeys\:"display RSA public keys"
+ purgecerts\:"purge cached certificates"
+ purgecrl\:"purge cached certificate revocation lists"
+ purgeike\:"purge IKE SAs without a quick mode or CHILD_SA"
+ purgeocsp\:"purge cached OCSP information"
+ reload\:"reload entire configuration (send SIGUSR1)"
+ rereadacerts\:"re-read attribute certificates"
+ rereadaacerts\:"flush and re-read authorization authority certificates"
+ rereadall\:"execute all re-read commands"
+ rereadcacerts\:"flush and re-read certificate authority certificates"
+ rereadcrls\:"re-read certificate revocation lists"
+ rereadocspcerts\:"re-read OCSP certificates"
+ rereadsecrets\:"flush and re-read secrets"
+ resetcounters\:"reset IKE counter information"
+ restart\:"equivalent to stop + start"
+ route\:"insert kernel IPsec policy for connection"
+ start\:"start IKE daemon"
+ status\:"display concise connection status"
+ statusall\:"display detailed connection status"
+ stop\:"terminate all IPsec connections and stop IKE daemon"
+ stroke\:"issue stroke command"
+ unroute\:"remove kernel IPsec policy for connection"
+ up\:"bring up IPsec connection"
+ update\:"reload changes in configuration (send SIGHUP)"
+ ))' \
+ '*:: :->next' \
+ && ret=0
+
+ [[ $state == next ]] &&
+ case $words[1] in
+ down)
+ _arguments : '1: :_ipsec_connections --instances' && ret=0
+ ;;
+ listcounters|resetcounters|route|status|statusall|unroute|up)
+ _arguments : '1: :_ipsec_connections' && ret=0
+ ;;
+ down-srcip)
+ _arguments : \
+ '1:virtual IP address (start)' \
+ '2::virtual IP address (end)' \
+ && ret=0
+ ;;
+ leases)
+ _arguments : '1:pool name' '2::virtual IP address' && ret=0
+ ;;
+ list*~list(counters|plugins))
+ _arguments : '--utc[use UTC for time fields]' && ret=0
+ ;;
+ start|restart)
+ _ipsec_starter && ret=0
+ ;;
+ stroke)
+ _arguments -s -S -A '-*' \
+ '(: * -)'{-h,--help}'[display help information]' \
+ '(-d --daemon)'{-d+,--daemon=}'[specify daemon name]:daemon name' \
+ '1: :_guard "^-*" "stroke command"' \
+ '*:stroke command argument:_default' \
+ && ret=0
+ ;;
+ esac
+
+ return ret
+}
+
+_ipsec "$@"
diff --git a/Completion/Unix/Command/_swanctl b/Completion/Unix/Command/_swanctl
new file mode 100644
index 000000000..ba2f5402d
--- /dev/null
+++ b/Completion/Unix/Command/_swanctl
@@ -0,0 +1,225 @@
+#compdef swanctl
+
+# Completion for strongSwan's swanctl. See also ipsec, which is deprecated but
+# still supported by strongSwan, and also used by Openswan/Libreswan.
+#
+# Note that in most cases elevated privileges are required to connect to the
+# VICI socket, so the gain-privileges style may be necessary to complete SA
+# names and the like: zstyle ':completion:*:swanctl/*' gain-privileges yes
+#
+# Other notes:
+# - One of swanctl's selling points is that it can provide 'raw' structured
+# responses for scripting, etc. In practice, though, the output formatted for
+# humans seems easier to 'parse' from the shell than the plist-like raw output
+# - @todo We don't complete authority names, pool names, peer IPs, etc.
+
+# Complete connection names, SA names, or SA unique IDs. The distinctions
+# between concepts like 'connections' and 'SAs' are very blurry here, partially
+# for convenience and partially due to author confusion
+# --child => complete only child/CHILD_SA names/IDs
+# --ids => complete unique SA IDs rather than connection/SA names
+# --ike => complete only connection/IKE_SA names/IDs
+(( $+functions[_swanctl_connections] )) ||
+_swanctl_connections() {
+ local i which
+ local -a expl tmp matches
+ local -A opts
+
+ zparseopts -D -E -A opts - -child -ids -ike
+
+ tmp=( ${(@M)${(f)"$(
+ _call_program -p swanctl-sas $words[1] -l
+ )"}:#[^:]##: \#<->*} )
+ (( $+opts[--ids] )) || tmp+=( ${(@M)${(f)"$(
+ _call_program -p swanctl-conns $words[1] -L
+ )"}:#[^:]##: ([A-Z][A-Za-z0-9]#|),*} )
+
+ for i in $tmp; do
+ if (( $+opts[--child] )) && [[ $i != [[:space:]]* ]]; then
+ continue
+ elif (( $+opts[--ike] )) && [[ $i == [[:space:]]* ]]; then
+ continue
+ fi
+
+ # <name>: #<unique id>, ...
+ i=${i//[#:,]/ }
+
+ if (( $+opts[--ids] )); then
+ matches+=( "${i[(w)2]}:${i[(w)1]} #${i[(w)2]}" )
+ else
+ matches+=( ${i[(w)1]} )
+ fi
+ done
+
+ if (( $+opts[--ids] )); then
+ matches=( ${(onu)matches} )
+ if (( $+opts[--child] )); then
+ which=CHILD_
+ elif (( $+opts[--ike] )); then
+ which=IKE_
+ fi
+ _describe -x2Vt sa-ids "${which}SA unique ID" matches
+ else
+ if (( $+opts[--child] )); then
+ which='child '
+ elif (( $+opts[--ike] )); then
+ which='IKE '
+ fi
+ _wanted -x connections expl "${which}connection/SA name" compadd - $matches
+ fi
+}
+
+_swanctl() {
+ # Although swanctl will correctly parse multiple short options in the first
+ # word, as in `swanctl -lh`, it won't actually *do* anything with the
+ # subsequent options -- so we'll require that they be separated. Also, --help
+ # doesn't take any further options, so just stop if we've got that
+ if (( CURRENT == 2 )) || [[ $words[2] == (-h*|--help) ]]; then
+ _arguments : \
+ '(-)'{-a,--load-pools}'[(re)load pool configuration]' \
+ '(-)'{-A,--list-pools}'[display loaded pool configurations]' \
+ '(-)'{-b,--load-authorities}'[(re)load authority configuration]' \
+ '(-)'{-B,--list-authorities}'[display loaded authority configurations]' \
+ '(-)'{-c,--load-conns}'[(re)load connection configuration]' \
+ '(-)'{-C,--counters}'[display or reset IKE event counters]' \
+ '(-)'{-d,--redirect}'[redirect IKE_SA]' \
+ '(-)'{-f,--flush-certs}'[flush cached certificates]' \
+ '(-)'{-g,--list-algs}'[display loaded algorithms]' \
+ '(-)'{-h,--help}'[display help information]' \
+ '(-)'{-i,--initiate}'[initiate a connection]' \
+ '(-)'{-l,--list-sas}'[display currently active IKE_SAs]' \
+ '(-)'{-L,--list-conns}'[display loaded configurations]' \
+ '(-)'{-m,--monitor-sa}'[monitor for IKE_SA and CHILD_SA changes]' \
+ '(-)'{-p,--install}'[install trap or shunt policy]' \
+ '(-)'{-P,--list-pols}'[display currently installed policies]' \
+ '(-)'{-q,--load-all}'[load credentials, authorities, pools, and connections]' \
+ '(-)'{-r,--reload-settings}'[reload daemon strongswan.conf]' \
+ '(-)'{-R,--rekey}'[rekey SA]' \
+ '(-)'{-s,--load-creds}'[(re)load credentials]' \
+ '(-)'{-S,--stats}'[display daemon statistics]' \
+ '(-)'{-t,--terminate}'[terminate connection]' \
+ '(-)'{-T,--log}'[trace logging output]' \
+ '(-)'{-u,--uninstall}'[uninstall trap or shunt policy]' \
+ '(-)'{-v,--version}'[display version information]' \
+ '(-)'{-x,--list-certs}'[display stored certificates]'
+ return
+ fi
+
+ local ret=1 cmd
+ local -a args cert_flags cert_types
+
+ cert_flags=( aa any ca none ocsp )
+ cert_types=( ocsp_response pubkey x509 x509_ac x509_crl )
+
+ if [[ $words[2] == -[^-]* ]]; then
+ cmd=${(M)words[2]#??}
+ else
+ cmd=$words[2]
+ fi
+ words=( $words[1] "${(@)words[3,-1]}" )
+ (( CURRENT-- ))
+
+ # Technically, only -v, -u, and -+ are truly global command options. However,
+ # in practice, all commands also support -h, -P, and -r
+ args=(
+ '(: * -)'{-h,--help}'[display help information]'
+ '(-P -r --pretty --raw)'{-P,--pretty}'[dump raw response message in pretty print]'
+ '(-P -r --pretty --raw)'{-r,--raw}'[dump raw response message]'
+ # https://wiki.strongswan.org/projects/strongswan/wiki/LoggerConfiguration
+ # https://github.com/strongswan/strongswan/blob/master/src/libstrongswan/utils/debug.h
+ '(-v --debug)'{-v+,--debug=}'[specify debug level]:debug level [1]:((
+ -1\:"absolutely silent (SILENT)"
+ 0\:"basic auditing (AUDIT)"
+ 1\:"generic control flow with errors (CTRL)"
+ 2\:"detailed control flow (DIAG)"
+ 3\:"raw binary blobs (RAW)"
+ 4\:"sensitive data (PRIVATE)"
+ ))'
+ '(-u --uri)'{-u+,--uri=}'[specify service URI to connect to]:VICI service URI:_urls'
+ '(-+ --options)'{'-\++',--options=}'[read command-line options from specified file]:options file:_files'
+ )
+
+ case $cmd in
+ -A|--list-pools) args+=(
+ '(-n --name)'{-n+,--name=}'[filter by specified pool name]:pool name'
+ '(-l --leases)'{-l,--leases}'[display leases of each pool]'
+ ) ;;
+ -B|--list-authorities) args+=(
+ '(-n --name)'{-n+,--name=}'[filter by specified authority name]:authority name'
+ ) ;;
+ -C|--counters) args+=(
+ '(-a -n --all --name)'{-a,--all}'[display/reset counters for all tracked connections]'
+ '(-a -n --all --name)'{-n+,--name=}'[specify connection name]: :_swanctl_connections --ike'
+ '(-r --reset)'{-r,--reset}'[reset counters]'
+ ) ;;
+ -d|--redirect) args+=(
+ '(-d --peer-id)'{-d+,--peer-id=}'[redirect by IKE_SA matching specified peer identity]:peer identity'
+ '(-g --gateway)'{-g+,--gateway=}'[redirect to specified gateway]:target gateway'
+ '(-i --ike)'{-i+,--ike=}'[redirect by specified IKE_SA name]: :_swanctl_connections --ike'
+ '(-I --ike-id)'{-I+,--ike-id=}'[redirect by specified IKE_SA unique ID]: :_swanctl_connections --ids --ike'
+ '(-p --peer-ip)'{-p+,--peer-ip=}'[redirect by IKE_SA matching specified peer IP]:peer IP address'
+ ) ;;
+ -f|--flush-certs) args+=(
+ '(-t --type)'{-t+,--type=}"[filter by specified certificate type]:certificate type:(
+ ${(j< >)${(@q-)cert_types}}
+ )"
+ ) ;;
+ -i|--initiate) args+=(
+ '(-c --child)'{-c+,--child=}'[specify CHILD_SA name]: :_swanctl_connections --child'
+ '(-i --ike)'{-i+,--ike=}"[specify CHILD_SA's connection name]: :_swanctl_connections --ike"
+ '(-t --timeout)'{-t+,--timeout=}'[specify timeout before detaching]:timeout (seconds)'
+ ) ;;
+ -l|--list-sas) args+=(
+ '(-i --ike)'{-i+,--ike=}'[filter by specified IKE_SA name]: :_swanctl_connections --ike'
+ '(-I --ike-id)'{-I+,--ike-id=}'[filter by specified IKE_SA unique ID]: :_swanctl_connections --ids --ike'
+ '(-n --noblock)'{-n,--noblock}'[do not wait for IKE_SAs in use]'
+ ) ;;
+ -p|-u|--install|--uninstall) args+=(
+ '(-c --child)'{-c+,--child=}'[specify CHILD_SA name]: :_swanctl_connections --child'
+ '(-i --ike)'{-i+,--ike=}"[specify CHILD_SA's connection name]: :_swanctl_connections --ike"
+ ) ;;
+ -P|--list-pols) args+=(
+ '(-c --child)'{-c+,--child=}'[filter by specified CHILD_SA name]: :_swanctl_connections --child'
+ '(-d --drop)'{-d,--drop}'[list drop policies]'
+ '(-p --pass)'{-p,--pass}'[list bypass policies]'
+ '(-t --trap)'{-t,--trap}'[list trap policies]'
+ ) ;;
+ -q|-s|--load-all|--load-creds) args+=(
+ '(-c --clear)'{-c,--clear}'[clear previously loaded credentials]'
+ '(-n --noprompt)'{-n,--noprompt}'[do not prompt for passwords]'
+ ) ;;
+ -R|--rekey) args+=(
+ '(-c --child)'{-c+,--child=}'[rekey by specified CHILD_SA name]: :_swanctl_connections --child'
+ '(-C --child-id)'{-C+,--child-id=}'[rekey by specified CHILD_SA unique ID]: :_swanctl_connections --ids --child'
+ '(-i --ike)'{-i+,--ike=}'[rekey by specified IKE_SA name]: :_swanctl_connections --ike'
+ '(-I --ike-id)'{-I+,--ike-id=}'[rekey by specified IKE_SA unique ID]: :_swanctl_connections --ids --ike'
+ ) ;;
+ -t|--terminate) args+=(
+ '(-t --timeout)'{-t+,--timeout=}'[specify timeout before detaching]:timeout (seconds)'
+ '(-c --child)'{-c+,--child=}'[terminate by specified CHILD_SA name]: :_swanctl_connections --child'
+ '(-C --child-id)'{-C+,--child-id=}'[terminate by specified CHILD_SA unique ID]: :_swanctl_connections --ids --child'
+ '(-i --ike)'{-i+,--ike=}'[terminate by specified IKE_SA name]: :_swanctl_connections --ike'
+ '(-I --ike-id)'{-I+,--ike-id=}'[terminate by specified IKE_SA unique ID]: :_swanctl_connections --ids --ike'
+ ) ;;
+ -v|--version) args+=(
+ '(-d --daemon)'{-d,--daemon}'[query daemon version]'
+ ) ;;
+ -x|--list-certs) args+=(
+ '(-f --flag)'{-f+,--flag=}"[filter by specified X.509 certificate flag]:certificate flag:(
+ ${(j< >)${(@q-)cert_flags}}
+ )"
+ '(-p --pem)'{-p,--pem}'[display PEM encoding of certificate]'
+ '(-s --subject)'{-s+,--subject=}'[filter by specified certificate subject]:certificate subject'
+ '(-S --short)'{-S,--short}'[omit some certificate details]'
+ '(-t --type)'{-t+,--type=}"[filter by specified certificate type]:certificate type:(
+ ${(j< >)${(@q-)cert_types}}
+ )"
+ '(-u --utc)'{-u,--utc}'[use UTC for time fields]'
+ ) ;;
+ esac
+
+ _arguments -s -S : $args && ret=0
+ return ret
+}
+
+_swanctl "$@"
diff --git a/Completion/Unix/Type/_urls b/Completion/Unix/Type/_urls
index e81eaac05..5d4990442 100644
--- a/Completion/Unix/Type/_urls
+++ b/Completion/Unix/Type/_urls
@@ -81,7 +81,7 @@ case "$scheme" in
return
fi
;;
- file)
+ file|unix)
[[ -prefix //(127.0.0.1|localhost)/ ]] && compset -P '//(127.0.0.1|localhost)'
[[ -prefix /// ]] && compset -P //
if ! compset -P //; then
Messages sorted by:
Reverse Date,
Date,
Thread,
Author