@@ -2272,33 +2272,47 @@ _included_ssh_config_files()
22722272 local configfile i files f
22732273 configfile=$1
22742274
2275+ # From man ssh_config:
2276+ # "Files without absolute paths are assumed to be in ~/.ssh if included
2277+ # in a user configuration file or /etc/ssh if included from the system
2278+ # configuration file."
2279+ # This behavior is not affected by the the including file location -
2280+ # if the system configuration file is included from the user's config,
2281+ # relative includes are still resolved in the user's ssh config directory.
2282+ local relative_include_base
2283+ if [[ $configfile == /etc/ssh* ]]; then
2284+ relative_include_base=" /etc/ssh"
2285+ else
2286+ relative_include_base=" $HOME /.ssh"
2287+ fi
2288+
2289+ local depth=1
22752290 local -a included
2276- _comp_split included " $( command sed -ne ' s/^[[:blank:]]*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][[:blank:]]\(.*\)$/\1/p ' " ${configfile} " ) " || return
2277-
2278- for i in " ${included[@]} " ; do
2279- # Check the origin of $configfile to complete relative included paths on included
2280- # files according to ssh_config(5):
2281- # "[...] Files without absolute paths are assumed to be in ~/.ssh if included in a user
2282- # configuration file or /etc/ssh if included from the system configuration file.[...]"
2283- if ! [[ $i =~ ^ \~ . * | ^ \/ . * ]] ; then
2284- if [[ $configfile =~ ^ \/ etc \/ ssh. * ]] ; then
2285- i= " /etc/ssh/ $i "
2286- else
2287- i=" $HOME /.ssh/ $i "
2291+ local -a include_files
2292+ included=( " $configfile " )
2293+
2294+ # Max recursion depth per openssh's READCONF_MAX_DEPTH:
2295+ # https://github.com/openssh/openssh-portable/blob/5ec5504f1d328d5bfa64280cd617c3efec4f78f3/readconf.c#L2240
2296+ local max_depth=16
2297+ while (( ${ # included[@]} > 0 && depth ++ < max_depth )) ; do
2298+ _comp_split include_files " $( command sed -ne ' s/^[[:blank:]]*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][[:blank:]]\(.*\)$/\1/p ' " ${included[@]} " ) " || return
2299+ included=()
2300+ for i in " ${include_files[@]} " ; do
2301+ if [[ $i != [~/] * ]] ; then
2302+ i=" ${relative_include_base} / ${i} "
22882303 fi
2289- fi
2290- __expand_tilde_by_ref i
2291- # In case the expanded variable contains multiple paths
2292- _comp_expand_glob files ' $i'
2293- if (( ${# files[@]} )) ; then
2294- for f in " ${files[@]} " ; do
2295- if [[ -r $f && ! -d $f ]]; then
2296- config+=(" $f " )
2297- # The Included file is processed to look for Included files in itself
2298- _included_ssh_config_files " $f "
2299- fi
2300- done
2301- fi
2304+ __expand_tilde_by_ref i
2305+ # In case the expanded variable contains multiple paths
2306+ _comp_expand_glob files ' $i'
2307+ if (( ${# files[@]} )) ; then
2308+ for f in " ${files[@]} " ; do
2309+ if [[ -r $f && ! -d $f ]]; then
2310+ config+=(" $f " )
2311+ included+=(" $f " )
2312+ fi
2313+ done
2314+ fi
2315+ done
23022316 done
23032317} # _included_ssh_config_files()
23042318
0 commit comments