113498266Sopenharmony_ci#***************************************************************************
213498266Sopenharmony_ci#                                  _   _ ____  _
313498266Sopenharmony_ci#  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci#                             / __| | | | |_) | |
513498266Sopenharmony_ci#                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci#                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci#
813498266Sopenharmony_ci# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci#
1013498266Sopenharmony_ci# This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci# you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci# are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci#
1413498266Sopenharmony_ci# You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci# copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci# furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci#
1813498266Sopenharmony_ci# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci# KIND, either express or implied.
2013498266Sopenharmony_ci#
2113498266Sopenharmony_ci# SPDX-License-Identifier: curl
2213498266Sopenharmony_ci#
2313498266Sopenharmony_ci#***************************************************************************
2413498266Sopenharmony_ci
2513498266Sopenharmony_cipackage sshhelp;
2613498266Sopenharmony_ci
2713498266Sopenharmony_ciuse strict;
2813498266Sopenharmony_ciuse warnings;
2913498266Sopenharmony_ci
3013498266Sopenharmony_ciBEGIN {
3113498266Sopenharmony_ci    use base qw(Exporter);
3213498266Sopenharmony_ci
3313498266Sopenharmony_ci    our @EXPORT_OK = qw(
3413498266Sopenharmony_ci        $sshdexe
3513498266Sopenharmony_ci        $sshexe
3613498266Sopenharmony_ci        $sftpsrvexe
3713498266Sopenharmony_ci        $sftpexe
3813498266Sopenharmony_ci        $sshkeygenexe
3913498266Sopenharmony_ci        $sshdconfig
4013498266Sopenharmony_ci        $sshconfig
4113498266Sopenharmony_ci        $sftpconfig
4213498266Sopenharmony_ci        $knownhosts
4313498266Sopenharmony_ci        $sshdlog
4413498266Sopenharmony_ci        $sshlog
4513498266Sopenharmony_ci        $sftplog
4613498266Sopenharmony_ci        $sftpcmds
4713498266Sopenharmony_ci        $hstprvkeyf
4813498266Sopenharmony_ci        $hstpubkeyf
4913498266Sopenharmony_ci        $hstpubmd5f
5013498266Sopenharmony_ci        $hstpubsha256f
5113498266Sopenharmony_ci        $cliprvkeyf
5213498266Sopenharmony_ci        $clipubkeyf
5313498266Sopenharmony_ci        display_sshdconfig
5413498266Sopenharmony_ci        display_sshconfig
5513498266Sopenharmony_ci        display_sftpconfig
5613498266Sopenharmony_ci        display_sshdlog
5713498266Sopenharmony_ci        display_sshlog
5813498266Sopenharmony_ci        display_sftplog
5913498266Sopenharmony_ci        dump_array
6013498266Sopenharmony_ci        find_sshd
6113498266Sopenharmony_ci        find_ssh
6213498266Sopenharmony_ci        find_sftpsrv
6313498266Sopenharmony_ci        find_sftp
6413498266Sopenharmony_ci        find_sshkeygen
6513498266Sopenharmony_ci        find_httptlssrv
6613498266Sopenharmony_ci        sshversioninfo
6713498266Sopenharmony_ci    );
6813498266Sopenharmony_ci}
6913498266Sopenharmony_ci
7013498266Sopenharmony_ciuse File::Spec;
7113498266Sopenharmony_ci
7213498266Sopenharmony_ciuse pathhelp qw(
7313498266Sopenharmony_ci    exe_ext
7413498266Sopenharmony_ci    );
7513498266Sopenharmony_ci
7613498266Sopenharmony_ci#***************************************************************************
7713498266Sopenharmony_ci# Global variables initialization
7813498266Sopenharmony_ci#
7913498266Sopenharmony_ciour $sshdexe         = 'sshd'        .exe_ext('SSH'); # base name and ext of ssh daemon
8013498266Sopenharmony_ciour $sshexe          = 'ssh'         .exe_ext('SSH'); # base name and ext of ssh client
8113498266Sopenharmony_ciour $sftpsrvexe      = 'sftp-server' .exe_ext('SSH'); # base name and ext of sftp-server
8213498266Sopenharmony_ciour $sftpexe         = 'sftp'        .exe_ext('SSH'); # base name and ext of sftp client
8313498266Sopenharmony_ciour $sshkeygenexe    = 'ssh-keygen'  .exe_ext('SSH'); # base name and ext of ssh-keygen
8413498266Sopenharmony_ciour $httptlssrvexe   = 'gnutls-serv' .exe_ext('SSH'); # base name and ext of gnutls-serv
8513498266Sopenharmony_ciour $sshdconfig      = 'curl_sshd_config';       # ssh daemon config file
8613498266Sopenharmony_ciour $sshconfig       = 'curl_ssh_config';        # ssh client config file
8713498266Sopenharmony_ciour $sftpconfig      = 'curl_sftp_config';       # sftp client config file
8813498266Sopenharmony_ciour $sshdlog         = undef;                    # ssh daemon log file
8913498266Sopenharmony_ciour $sshlog          = undef;                    # ssh client log file
9013498266Sopenharmony_ciour $sftplog         = undef;                    # sftp client log file
9113498266Sopenharmony_ciour $sftpcmds        = 'curl_sftp_cmds';         # sftp client commands batch file
9213498266Sopenharmony_ciour $knownhosts      = 'curl_client_knownhosts'; # ssh knownhosts file
9313498266Sopenharmony_ciour $hstprvkeyf      = 'curl_host_rsa_key';      # host private key file
9413498266Sopenharmony_ciour $hstpubkeyf      = 'curl_host_rsa_key.pub';  # host public key file
9513498266Sopenharmony_ciour $hstpubmd5f      = 'curl_host_rsa_key.pub_md5';  # md5 hash of host public key
9613498266Sopenharmony_ciour $hstpubsha256f   = 'curl_host_rsa_key.pub_sha256';  # sha256 hash of host public key
9713498266Sopenharmony_ciour $cliprvkeyf      = 'curl_client_key';        # client private key file
9813498266Sopenharmony_ciour $clipubkeyf      = 'curl_client_key.pub';    # client public key file
9913498266Sopenharmony_ci
10013498266Sopenharmony_ci
10113498266Sopenharmony_ci#***************************************************************************
10213498266Sopenharmony_ci# Absolute paths where to look for sftp-server plugin, when not in PATH
10313498266Sopenharmony_ci#
10413498266Sopenharmony_ciour @sftppath = qw(
10513498266Sopenharmony_ci    /usr/lib/openssh
10613498266Sopenharmony_ci    /usr/libexec/openssh
10713498266Sopenharmony_ci    /usr/libexec
10813498266Sopenharmony_ci    /usr/local/libexec
10913498266Sopenharmony_ci    /opt/local/libexec
11013498266Sopenharmony_ci    /usr/lib/ssh
11113498266Sopenharmony_ci    /usr/libexec/ssh
11213498266Sopenharmony_ci    /usr/sbin
11313498266Sopenharmony_ci    /usr/lib
11413498266Sopenharmony_ci    /usr/lib/ssh/openssh
11513498266Sopenharmony_ci    /usr/lib64/ssh
11613498266Sopenharmony_ci    /usr/lib64/misc
11713498266Sopenharmony_ci    /usr/lib/misc
11813498266Sopenharmony_ci    /usr/local/sbin
11913498266Sopenharmony_ci    /usr/freeware/bin
12013498266Sopenharmony_ci    /usr/freeware/sbin
12113498266Sopenharmony_ci    /usr/freeware/libexec
12213498266Sopenharmony_ci    /opt/ssh/sbin
12313498266Sopenharmony_ci    /opt/ssh/libexec
12413498266Sopenharmony_ci    );
12513498266Sopenharmony_ci
12613498266Sopenharmony_ci
12713498266Sopenharmony_ci#***************************************************************************
12813498266Sopenharmony_ci# Absolute paths where to look for httptlssrv (gnutls-serv), when not in PATH
12913498266Sopenharmony_ci#
13013498266Sopenharmony_ciour @httptlssrvpath = qw(
13113498266Sopenharmony_ci    /usr/sbin
13213498266Sopenharmony_ci    /usr/libexec
13313498266Sopenharmony_ci    /usr/lib
13413498266Sopenharmony_ci    /usr/lib/misc
13513498266Sopenharmony_ci    /usr/lib64/misc
13613498266Sopenharmony_ci    /usr/local/bin
13713498266Sopenharmony_ci    /usr/local/sbin
13813498266Sopenharmony_ci    /usr/local/libexec
13913498266Sopenharmony_ci    /opt/local/bin
14013498266Sopenharmony_ci    /opt/local/sbin
14113498266Sopenharmony_ci    /opt/local/libexec
14213498266Sopenharmony_ci    /usr/freeware/bin
14313498266Sopenharmony_ci    /usr/freeware/sbin
14413498266Sopenharmony_ci    /usr/freeware/libexec
14513498266Sopenharmony_ci    /opt/gnutls/bin
14613498266Sopenharmony_ci    /opt/gnutls/sbin
14713498266Sopenharmony_ci    /opt/gnutls/libexec
14813498266Sopenharmony_ci    );
14913498266Sopenharmony_ci
15013498266Sopenharmony_ci
15113498266Sopenharmony_ci#***************************************************************************
15213498266Sopenharmony_ci# Create or overwrite the given file with lines from an array of strings
15313498266Sopenharmony_ci#
15413498266Sopenharmony_cisub dump_array {
15513498266Sopenharmony_ci    my ($filename, @arr) = @_;
15613498266Sopenharmony_ci    my $error;
15713498266Sopenharmony_ci
15813498266Sopenharmony_ci    if(!$filename) {
15913498266Sopenharmony_ci        $error = 'Error: Missing argument 1 for dump_array()';
16013498266Sopenharmony_ci    }
16113498266Sopenharmony_ci    elsif(open(my $textfh, ">", $filename)) {
16213498266Sopenharmony_ci        foreach my $line (@arr) {
16313498266Sopenharmony_ci            $line .= "\n" if($line !~ /\n$/);
16413498266Sopenharmony_ci            print $textfh $line;
16513498266Sopenharmony_ci        }
16613498266Sopenharmony_ci        if(!close($textfh)) {
16713498266Sopenharmony_ci            $error = "Error: cannot close file $filename";
16813498266Sopenharmony_ci        }
16913498266Sopenharmony_ci    }
17013498266Sopenharmony_ci    else {
17113498266Sopenharmony_ci        $error = "Error: cannot write file $filename";
17213498266Sopenharmony_ci    }
17313498266Sopenharmony_ci    return $error;
17413498266Sopenharmony_ci}
17513498266Sopenharmony_ci
17613498266Sopenharmony_ci
17713498266Sopenharmony_ci#***************************************************************************
17813498266Sopenharmony_ci# Display contents of the given file
17913498266Sopenharmony_ci#
18013498266Sopenharmony_cisub display_file {
18113498266Sopenharmony_ci    my $filename = $_[0];
18213498266Sopenharmony_ci    print "=== Start of file $filename\n";
18313498266Sopenharmony_ci    if(open(my $displayfh, "<", "$filename")) {
18413498266Sopenharmony_ci        while(my $line = <$displayfh>) {
18513498266Sopenharmony_ci            print "$line";
18613498266Sopenharmony_ci        }
18713498266Sopenharmony_ci        close $displayfh;
18813498266Sopenharmony_ci    }
18913498266Sopenharmony_ci    print "=== End of file $filename\n";
19013498266Sopenharmony_ci}
19113498266Sopenharmony_ci
19213498266Sopenharmony_ci
19313498266Sopenharmony_ci#***************************************************************************
19413498266Sopenharmony_ci# Display contents of the ssh daemon config file
19513498266Sopenharmony_ci#
19613498266Sopenharmony_cisub display_sshdconfig {
19713498266Sopenharmony_ci    display_file($sshdconfig);
19813498266Sopenharmony_ci}
19913498266Sopenharmony_ci
20013498266Sopenharmony_ci
20113498266Sopenharmony_ci#***************************************************************************
20213498266Sopenharmony_ci# Display contents of the ssh client config file
20313498266Sopenharmony_ci#
20413498266Sopenharmony_cisub display_sshconfig {
20513498266Sopenharmony_ci    display_file($sshconfig);
20613498266Sopenharmony_ci}
20713498266Sopenharmony_ci
20813498266Sopenharmony_ci
20913498266Sopenharmony_ci#***************************************************************************
21013498266Sopenharmony_ci# Display contents of the sftp client config file
21113498266Sopenharmony_ci#
21213498266Sopenharmony_cisub display_sftpconfig {
21313498266Sopenharmony_ci    display_file($sftpconfig);
21413498266Sopenharmony_ci}
21513498266Sopenharmony_ci
21613498266Sopenharmony_ci
21713498266Sopenharmony_ci#***************************************************************************
21813498266Sopenharmony_ci# Display contents of the ssh daemon log file
21913498266Sopenharmony_ci#
22013498266Sopenharmony_cisub display_sshdlog {
22113498266Sopenharmony_ci    die "error: \$sshdlog uninitialized" if(not defined $sshdlog);
22213498266Sopenharmony_ci    display_file($sshdlog);
22313498266Sopenharmony_ci}
22413498266Sopenharmony_ci
22513498266Sopenharmony_ci
22613498266Sopenharmony_ci#***************************************************************************
22713498266Sopenharmony_ci# Display contents of the ssh client log file
22813498266Sopenharmony_ci#
22913498266Sopenharmony_cisub display_sshlog {
23013498266Sopenharmony_ci    die "error: \$sshlog uninitialized" if(not defined $sshlog);
23113498266Sopenharmony_ci    display_file($sshlog);
23213498266Sopenharmony_ci}
23313498266Sopenharmony_ci
23413498266Sopenharmony_ci
23513498266Sopenharmony_ci#***************************************************************************
23613498266Sopenharmony_ci# Display contents of the sftp client log file
23713498266Sopenharmony_ci#
23813498266Sopenharmony_cisub display_sftplog {
23913498266Sopenharmony_ci    die "error: \$sftplog uninitialized" if(not defined $sftplog);
24013498266Sopenharmony_ci    display_file($sftplog);
24113498266Sopenharmony_ci}
24213498266Sopenharmony_ci
24313498266Sopenharmony_ci
24413498266Sopenharmony_ci#***************************************************************************
24513498266Sopenharmony_ci# Find a file somewhere in the given path
24613498266Sopenharmony_ci#
24713498266Sopenharmony_cisub find_file {
24813498266Sopenharmony_ci    my $fn = $_[0];
24913498266Sopenharmony_ci    shift;
25013498266Sopenharmony_ci    my @path = @_;
25113498266Sopenharmony_ci    foreach (@path) {
25213498266Sopenharmony_ci        my $file = File::Spec->catfile($_, $fn);
25313498266Sopenharmony_ci        if(-e $file && ! -d $file) {
25413498266Sopenharmony_ci            return $file;
25513498266Sopenharmony_ci        }
25613498266Sopenharmony_ci    }
25713498266Sopenharmony_ci    return "";
25813498266Sopenharmony_ci}
25913498266Sopenharmony_ci
26013498266Sopenharmony_ci
26113498266Sopenharmony_ci#***************************************************************************
26213498266Sopenharmony_ci# Find an executable file somewhere in the given path
26313498266Sopenharmony_ci#
26413498266Sopenharmony_cisub find_exe_file {
26513498266Sopenharmony_ci    my $fn = $_[0];
26613498266Sopenharmony_ci    shift;
26713498266Sopenharmony_ci    my @path = @_;
26813498266Sopenharmony_ci    my $xext = exe_ext('SSH');
26913498266Sopenharmony_ci    foreach (@path) {
27013498266Sopenharmony_ci        my $file = File::Spec->catfile($_, $fn);
27113498266Sopenharmony_ci        if(-e $file && ! -d $file) {
27213498266Sopenharmony_ci            return $file if(-x $file);
27313498266Sopenharmony_ci            return $file if(($xext) && (lc($file) =~ /\Q$xext\E$/));
27413498266Sopenharmony_ci        }
27513498266Sopenharmony_ci    }
27613498266Sopenharmony_ci    return "";
27713498266Sopenharmony_ci}
27813498266Sopenharmony_ci
27913498266Sopenharmony_ci
28013498266Sopenharmony_ci#***************************************************************************
28113498266Sopenharmony_ci# Find a file in environment path or in our sftppath
28213498266Sopenharmony_ci#
28313498266Sopenharmony_cisub find_file_spath {
28413498266Sopenharmony_ci    my $filename = $_[0];
28513498266Sopenharmony_ci    my @spath;
28613498266Sopenharmony_ci    push(@spath, File::Spec->path());
28713498266Sopenharmony_ci    push(@spath, @sftppath);
28813498266Sopenharmony_ci    return find_file($filename, @spath);
28913498266Sopenharmony_ci}
29013498266Sopenharmony_ci
29113498266Sopenharmony_ci
29213498266Sopenharmony_ci#***************************************************************************
29313498266Sopenharmony_ci# Find an executable file in environment path or in our httptlssrvpath
29413498266Sopenharmony_ci#
29513498266Sopenharmony_cisub find_exe_file_hpath {
29613498266Sopenharmony_ci    my $filename = $_[0];
29713498266Sopenharmony_ci    my @hpath;
29813498266Sopenharmony_ci    push(@hpath, File::Spec->path());
29913498266Sopenharmony_ci    push(@hpath, @httptlssrvpath);
30013498266Sopenharmony_ci    return find_exe_file($filename, @hpath);
30113498266Sopenharmony_ci}
30213498266Sopenharmony_ci
30313498266Sopenharmony_ci
30413498266Sopenharmony_ci#***************************************************************************
30513498266Sopenharmony_ci# Find ssh daemon and return canonical filename
30613498266Sopenharmony_ci#
30713498266Sopenharmony_cisub find_sshd {
30813498266Sopenharmony_ci    return find_file_spath($sshdexe);
30913498266Sopenharmony_ci}
31013498266Sopenharmony_ci
31113498266Sopenharmony_ci
31213498266Sopenharmony_ci#***************************************************************************
31313498266Sopenharmony_ci# Find ssh client and return canonical filename
31413498266Sopenharmony_ci#
31513498266Sopenharmony_cisub find_ssh {
31613498266Sopenharmony_ci    return find_file_spath($sshexe);
31713498266Sopenharmony_ci}
31813498266Sopenharmony_ci
31913498266Sopenharmony_ci
32013498266Sopenharmony_ci#***************************************************************************
32113498266Sopenharmony_ci# Find sftp-server plugin and return canonical filename
32213498266Sopenharmony_ci#
32313498266Sopenharmony_cisub find_sftpsrv {
32413498266Sopenharmony_ci    return find_file_spath($sftpsrvexe);
32513498266Sopenharmony_ci}
32613498266Sopenharmony_ci
32713498266Sopenharmony_ci
32813498266Sopenharmony_ci#***************************************************************************
32913498266Sopenharmony_ci# Find sftp client and return canonical filename
33013498266Sopenharmony_ci#
33113498266Sopenharmony_cisub find_sftp {
33213498266Sopenharmony_ci    return find_file_spath($sftpexe);
33313498266Sopenharmony_ci}
33413498266Sopenharmony_ci
33513498266Sopenharmony_ci
33613498266Sopenharmony_ci#***************************************************************************
33713498266Sopenharmony_ci# Find ssh-keygen and return canonical filename
33813498266Sopenharmony_ci#
33913498266Sopenharmony_cisub find_sshkeygen {
34013498266Sopenharmony_ci    return find_file_spath($sshkeygenexe);
34113498266Sopenharmony_ci}
34213498266Sopenharmony_ci
34313498266Sopenharmony_ci
34413498266Sopenharmony_ci#***************************************************************************
34513498266Sopenharmony_ci# Find httptlssrv (gnutls-serv) and return canonical filename
34613498266Sopenharmony_ci#
34713498266Sopenharmony_cisub find_httptlssrv {
34813498266Sopenharmony_ci    my $p = find_exe_file_hpath($httptlssrvexe);
34913498266Sopenharmony_ci    if($p) {
35013498266Sopenharmony_ci        my @o = `"$p" -l`;
35113498266Sopenharmony_ci        my $found;
35213498266Sopenharmony_ci        for(@o) {
35313498266Sopenharmony_ci            if(/Key exchange: SRP/) {
35413498266Sopenharmony_ci                $found = 1;
35513498266Sopenharmony_ci                last;
35613498266Sopenharmony_ci            }
35713498266Sopenharmony_ci        }
35813498266Sopenharmony_ci        return $p if($found);
35913498266Sopenharmony_ci    }
36013498266Sopenharmony_ci    return "";
36113498266Sopenharmony_ci}
36213498266Sopenharmony_ci
36313498266Sopenharmony_ci
36413498266Sopenharmony_ci#***************************************************************************
36513498266Sopenharmony_ci# Return version info for the given ssh client or server binaries
36613498266Sopenharmony_ci#
36713498266Sopenharmony_cisub sshversioninfo {
36813498266Sopenharmony_ci    my $sshbin = $_[0]; # canonical filename
36913498266Sopenharmony_ci    my $major;
37013498266Sopenharmony_ci    my $minor;
37113498266Sopenharmony_ci    my $patch;
37213498266Sopenharmony_ci    my $sshid;
37313498266Sopenharmony_ci    my $versnum;
37413498266Sopenharmony_ci    my $versstr;
37513498266Sopenharmony_ci    my $error;
37613498266Sopenharmony_ci
37713498266Sopenharmony_ci    if(!$sshbin) {
37813498266Sopenharmony_ci        $error = 'Error: Missing argument 1 for sshversioninfo()';
37913498266Sopenharmony_ci    }
38013498266Sopenharmony_ci    elsif(! -x $sshbin) {
38113498266Sopenharmony_ci        $error = "Error: cannot read or execute $sshbin";
38213498266Sopenharmony_ci    }
38313498266Sopenharmony_ci    else {
38413498266Sopenharmony_ci        my $cmd = ($sshbin =~ /$sshdexe$/) ? "\"$sshbin\" -?" : "\"$sshbin\" -V";
38513498266Sopenharmony_ci        $error = "$cmd\n";
38613498266Sopenharmony_ci        foreach my $tmpstr (qx($cmd 2>&1)) {
38713498266Sopenharmony_ci            if($tmpstr =~ /OpenSSH[_-](\d+)\.(\d+)(\.(\d+))*/i) {
38813498266Sopenharmony_ci                $major = $1;
38913498266Sopenharmony_ci                $minor = $2;
39013498266Sopenharmony_ci                $patch = $4?$4:0;
39113498266Sopenharmony_ci                $sshid = 'OpenSSH';
39213498266Sopenharmony_ci                $versnum = (100*$major) + (10*$minor) + $patch;
39313498266Sopenharmony_ci                $versstr = "$sshid $major.$minor.$patch";
39413498266Sopenharmony_ci                $error = undef;
39513498266Sopenharmony_ci                last;
39613498266Sopenharmony_ci            }
39713498266Sopenharmony_ci            if($tmpstr =~ /OpenSSH[_-]for[_-]Windows[_-](\d+)\.(\d+)(\.(\d+))*/i) {
39813498266Sopenharmony_ci                $major = $1;
39913498266Sopenharmony_ci                $minor = $2;
40013498266Sopenharmony_ci                $patch = $4?$4:0;
40113498266Sopenharmony_ci                $sshid = 'OpenSSH-Windows';
40213498266Sopenharmony_ci                $versnum = (100*$major) + (10*$minor) + $patch;
40313498266Sopenharmony_ci                $versstr = "$sshid $major.$minor.$patch";
40413498266Sopenharmony_ci                $error = undef;
40513498266Sopenharmony_ci                last;
40613498266Sopenharmony_ci            }
40713498266Sopenharmony_ci            if($tmpstr =~ /Sun[_-]SSH[_-](\d+)\.(\d+)(\.(\d+))*/i) {
40813498266Sopenharmony_ci                $major = $1;
40913498266Sopenharmony_ci                $minor = $2;
41013498266Sopenharmony_ci                $patch = $4?$4:0;
41113498266Sopenharmony_ci                $sshid = 'SunSSH';
41213498266Sopenharmony_ci                $versnum = (100*$major) + (10*$minor) + $patch;
41313498266Sopenharmony_ci                $versstr = "$sshid $major.$minor.$patch";
41413498266Sopenharmony_ci                $error = undef;
41513498266Sopenharmony_ci                last;
41613498266Sopenharmony_ci            }
41713498266Sopenharmony_ci            $error .= $tmpstr;
41813498266Sopenharmony_ci        }
41913498266Sopenharmony_ci        chomp $error if($error);
42013498266Sopenharmony_ci    }
42113498266Sopenharmony_ci    return ($sshid, $versnum, $versstr, $error);
42213498266Sopenharmony_ci}
42313498266Sopenharmony_ci
42413498266Sopenharmony_ci
42513498266Sopenharmony_ci#***************************************************************************
42613498266Sopenharmony_ci# End of library
42713498266Sopenharmony_ci1;
428