1 #***************************************************************************
3 # Project ___| | | | _ \| |
5 # | (__| |_| | _ <| |___
6 # \___|\___/|_| \_\_____|
8 # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
10 # This software is licensed as described in the file COPYING, which
11 # you should have received as part of this distribution. The terms
12 # are also available at https://curl.se/docs/copyright.html.
14 # You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 # copies of the Software, and permit persons to whom the Software is
16 # furnished to do so, under the terms of the COPYING file.
18 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 # KIND, either express or implied.
21 # SPDX-License-Identifier: curl
23 #***************************************************************************
31 use base qw(Exporter);
76 #***************************************************************************
77 # Global variables initialization
79 our $sshdexe = 'sshd' .exe_ext('SSH'); # base name and ext of ssh daemon
80 our $sshexe = 'ssh' .exe_ext('SSH'); # base name and ext of ssh client
81 our $sftpsrvexe = 'sftp-server' .exe_ext('SSH'); # base name and ext of sftp-server
82 our $sftpexe = 'sftp' .exe_ext('SSH'); # base name and ext of sftp client
83 our $sshkeygenexe = 'ssh-keygen' .exe_ext('SSH'); # base name and ext of ssh-keygen
84 our $httptlssrvexe = 'gnutls-serv' .exe_ext('SSH'); # base name and ext of gnutls-serv
85 our $sshdconfig = 'curl_sshd_config'; # ssh daemon config file
86 our $sshconfig = 'curl_ssh_config'; # ssh client config file
87 our $sftpconfig = 'curl_sftp_config'; # sftp client config file
88 our $sshdlog = undef; # ssh daemon log file
89 our $sshlog = undef; # ssh client log file
90 our $sftplog = undef; # sftp client log file
91 our $sftpcmds = 'curl_sftp_cmds'; # sftp client commands batch file
92 our $knownhosts = 'curl_client_knownhosts'; # ssh knownhosts file
93 our $hstprvkeyf = 'curl_host_rsa_key'; # host private key file
94 our $hstpubkeyf = 'curl_host_rsa_key.pub'; # host public key file
95 our $hstpubmd5f = 'curl_host_rsa_key.pub_md5'; # md5 hash of host public key
96 our $hstpubsha256f = 'curl_host_rsa_key.pub_sha256'; # sha256 hash of host public key
97 our $cliprvkeyf = 'curl_client_key'; # client private key file
98 our $clipubkeyf = 'curl_client_key.pub'; # client public key file
101 #***************************************************************************
102 # Absolute paths where to look for sftp-server plugin, when not in PATH
121 /usr/freeware/libexec
127 #***************************************************************************
128 # Absolute paths where to look for httptlssrv (gnutls-serv), when not in PATH
130 our @httptlssrvpath = qw(
144 /usr/freeware/libexec
151 #***************************************************************************
152 # Create or overwrite the given file with lines from an array of strings
155 my ($filename, @arr) = @_;
159 $error = 'Error: Missing argument 1 for dump_array()';
161 elsif(open(my $textfh, ">", $filename)) {
162 foreach my $line (@arr) {
163 $line .= "\n" if($line !~ /\n$/);
166 if(!close($textfh)) {
167 $error = "Error: cannot close file $filename";
171 $error = "Error: cannot write file $filename";
177 #***************************************************************************
178 # Display contents of the given file
181 my $filename = $_[0];
182 print "=== Start of file $filename\n";
183 if(open(my $displayfh, "<", "$filename")) {
184 while(my $line = <$displayfh>) {
189 print "=== End of file $filename\n";
193 #***************************************************************************
194 # Display contents of the ssh daemon config file
196 sub display_sshdconfig {
197 display_file($sshdconfig);
201 #***************************************************************************
202 # Display contents of the ssh client config file
204 sub display_sshconfig {
205 display_file($sshconfig);
209 #***************************************************************************
210 # Display contents of the sftp client config file
212 sub display_sftpconfig {
213 display_file($sftpconfig);
217 #***************************************************************************
218 # Display contents of the ssh daemon log file
220 sub display_sshdlog {
221 die "error: \$sshdlog uninitialized" if(not defined $sshdlog);
222 display_file($sshdlog);
226 #***************************************************************************
227 # Display contents of the ssh client log file
230 die "error: \$sshlog uninitialized" if(not defined $sshlog);
231 display_file($sshlog);
235 #***************************************************************************
236 # Display contents of the sftp client log file
238 sub display_sftplog {
239 die "error: \$sftplog uninitialized" if(not defined $sftplog);
240 display_file($sftplog);
244 #***************************************************************************
245 # Find a file somewhere in the given path
252 my $file = File::Spec->catfile($_, $fn);
253 if(-e $file && ! -d $file) {
261 #***************************************************************************
262 # Find an executable file somewhere in the given path
268 my $xext = exe_ext('SSH');
270 my $file = File::Spec->catfile($_, $fn);
271 if(-e $file && ! -d $file) {
272 return $file if(-x $file);
273 return $file if(($xext) && (lc($file) =~ /\Q$xext\E$/));
280 #***************************************************************************
281 # Find a file in environment path or in our sftppath
283 sub find_file_spath {
284 my $filename = $_[0];
286 push(@spath, File::Spec->path());
287 push(@spath, @sftppath);
288 return find_file($filename, @spath);
292 #***************************************************************************
293 # Find an executable file in environment path or in our httptlssrvpath
295 sub find_exe_file_hpath {
296 my $filename = $_[0];
298 push(@hpath, File::Spec->path());
299 push(@hpath, @httptlssrvpath);
300 return find_exe_file($filename, @hpath);
304 #***************************************************************************
305 # Find ssh daemon and return canonical filename
308 return find_file_spath($sshdexe);
312 #***************************************************************************
313 # Find ssh client and return canonical filename
316 return find_file_spath($sshexe);
320 #***************************************************************************
321 # Find sftp-server plugin and return canonical filename
324 return find_file_spath($sftpsrvexe);
328 #***************************************************************************
329 # Find sftp client and return canonical filename
332 return find_file_spath($sftpexe);
336 #***************************************************************************
337 # Find ssh-keygen and return canonical filename
340 return find_file_spath($sshkeygenexe);
344 #***************************************************************************
345 # Find httptlssrv (gnutls-serv) and return canonical filename
347 sub find_httptlssrv {
348 my $p = find_exe_file_hpath($httptlssrvexe);
353 if(/Key exchange: SRP/) {
358 return $p if($found);
364 #***************************************************************************
365 # Return version info for the given ssh client or server binaries
368 my $sshbin = $_[0]; # canonical filename
378 $error = 'Error: Missing argument 1 for sshversioninfo()';
380 elsif(! -x $sshbin) {
381 $error = "Error: cannot read or execute $sshbin";
384 my $cmd = ($sshbin =~ /$sshdexe$/) ? "\"$sshbin\" -?" : "\"$sshbin\" -V";
386 foreach my $tmpstr (qx($cmd 2>&1)) {
387 if($tmpstr =~ /OpenSSH[_-](\d+)\.(\d+)(\.(\d+))*/i) {
392 $versnum = (100*$major) + (10*$minor) + $patch;
393 $versstr = "$sshid $major.$minor.$patch";
397 if($tmpstr =~ /OpenSSH[_-]for[_-]Windows[_-](\d+)\.(\d+)(\.(\d+))*/i) {
401 $sshid = 'OpenSSH-Windows';
402 $versnum = (100*$major) + (10*$minor) + $patch;
403 $versstr = "$sshid $major.$minor.$patch";
407 if($tmpstr =~ /Sun[_-]SSH[_-](\d+)\.(\d+)(\.(\d+))*/i) {
412 $versnum = (100*$major) + (10*$minor) + $patch;
413 $versstr = "$sshid $major.$minor.$patch";
419 chomp $error if($error);
421 return ($sshid, $versnum, $versstr, $error);
425 #***************************************************************************