sshhelp.pm (12435B)
1 #*************************************************************************** 2 # _ _ ____ _ 3 # Project ___| | | | _ \| | 4 # / __| | | | |_) | | 5 # | (__| |_| | _ <| |___ 6 # \___|\___/|_| \_\_____| 7 # 8 # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 # 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. 13 # 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. 17 # 18 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 # KIND, either express or implied. 20 # 21 # SPDX-License-Identifier: curl 22 # 23 #*************************************************************************** 24 25 package sshhelp; 26 27 use strict; 28 use warnings; 29 30 BEGIN { 31 use base qw(Exporter); 32 33 our @EXPORT_OK = qw( 34 $sshdexe 35 $sshexe 36 $sftpsrvexe 37 $sftpexe 38 $sshkeygenexe 39 $sshdconfig 40 $sshconfig 41 $sftpconfig 42 $knownhosts 43 $sshdlog 44 $sshlog 45 $sftplog 46 $sftpcmds 47 $hstprvkeyf 48 $hstpubkeyf 49 $hstpubmd5f 50 $hstpubsha256f 51 $cliprvkeyf 52 $clipubkeyf 53 display_file_top 54 display_sshdconfig 55 display_sshconfig 56 display_sftpconfig 57 display_sshdlog 58 display_sshlog 59 display_sftplog 60 dump_array 61 find_sshd 62 find_ssh 63 find_sftpsrv 64 find_sftp 65 find_sshkeygen 66 find_httptlssrv 67 sshversioninfo 68 ); 69 } 70 71 use File::Spec; 72 73 use pathhelp qw( 74 exe_ext 75 ); 76 77 #*************************************************************************** 78 # Global variables initialization 79 # 80 our $sshdexe = 'sshd' .exe_ext('SSH'); # base name and ext of ssh daemon 81 our $sshexe = 'ssh' .exe_ext('SSH'); # base name and ext of ssh client 82 our $sftpsrvexe = 'sftp-server' .exe_ext('SSH'); # base name and ext of sftp-server 83 our $sftpexe = 'sftp' .exe_ext('SSH'); # base name and ext of sftp client 84 our $sshkeygenexe = 'ssh-keygen' .exe_ext('SSH'); # base name and ext of ssh-keygen 85 our $httptlssrvexe = 'gnutls-serv' .exe_ext('SSH'); # base name and ext of gnutls-serv 86 our $sshdconfig = 'curl_sshd_config'; # ssh daemon config file 87 our $sshconfig = 'curl_ssh_config'; # ssh client config file 88 our $sftpconfig = 'curl_sftp_config'; # sftp client config file 89 our $sshdlog = undef; # ssh daemon log file 90 our $sshlog = undef; # ssh client log file 91 our $sftplog = undef; # sftp client log file 92 our $sftpcmds = 'curl_sftp_cmds'; # sftp client commands batch file 93 our $knownhosts = 'curl_client_knownhosts'; # ssh knownhosts file 94 our $hstprvkeyf = 'curl_host_rsa_key'; # host private key file 95 our $hstpubkeyf = 'curl_host_rsa_key.pub'; # host public key file 96 our $hstpubmd5f = 'curl_host_rsa_key.pub_md5'; # md5 hash of host public key 97 our $hstpubsha256f = 'curl_host_rsa_key.pub_sha256'; # sha256 hash of host public key 98 our $cliprvkeyf = 'curl_client_key'; # client private key file 99 our $clipubkeyf = 'curl_client_key.pub'; # client public key file 100 101 102 #*************************************************************************** 103 # Absolute paths where to look for sftp-server plugin, when not in PATH 104 # 105 our @sftppath = qw( 106 /usr/lib/openssh 107 /usr/libexec/openssh 108 /usr/libexec 109 /usr/local/libexec 110 /opt/local/libexec 111 /usr/lib/ssh 112 /usr/libexec/ssh 113 /usr/sbin 114 /usr/lib 115 /usr/lib/ssh/openssh 116 /usr/lib64/ssh 117 /usr/lib64/misc 118 /usr/lib/misc 119 /usr/local/sbin 120 /usr/freeware/bin 121 /usr/freeware/sbin 122 /usr/freeware/libexec 123 /opt/ssh/sbin 124 /opt/ssh/libexec 125 ); 126 127 128 #*************************************************************************** 129 # Absolute paths where to look for httptlssrv (gnutls-serv), when not in PATH 130 # 131 our @httptlssrvpath = qw( 132 /usr/sbin 133 /usr/libexec 134 /usr/lib 135 /usr/lib/misc 136 /usr/lib64/misc 137 /usr/local/bin 138 /usr/local/sbin 139 /usr/local/libexec 140 /opt/local/bin 141 /opt/local/sbin 142 /opt/local/libexec 143 /usr/freeware/bin 144 /usr/freeware/sbin 145 /usr/freeware/libexec 146 /opt/gnutls/bin 147 /opt/gnutls/sbin 148 /opt/gnutls/libexec 149 ); 150 151 152 #*************************************************************************** 153 # Create or overwrite the given file with lines from an array of strings 154 # 155 sub dump_array { 156 my ($filename, @arr) = @_; 157 my $error; 158 159 if(!$filename) { 160 $error = 'Error: Missing argument 1 for dump_array()'; 161 } 162 elsif(open(my $textfh, ">", $filename)) { 163 foreach my $line (@arr) { 164 $line .= "\n" if($line !~ /\n$/); 165 print $textfh $line; 166 } 167 if(!close($textfh)) { 168 $error = "Error: cannot close file $filename"; 169 } 170 } 171 else { 172 $error = "Error: cannot write file $filename"; 173 } 174 return $error; 175 } 176 177 178 #*************************************************************************** 179 # Display contents of the given file 180 # 181 sub display_file { 182 my $filename = $_[0]; 183 print "=== Start of file $filename\n"; 184 if(open(my $displayfh, "<", "$filename")) { 185 while(my $line = <$displayfh>) { 186 print "$line"; 187 } 188 close $displayfh; 189 } 190 print "=== End of file $filename\n"; 191 } 192 193 194 #*************************************************************************** 195 # Display first line of the given file 196 # 197 sub display_file_top { 198 my $filename = $_[0]; 199 print "=== Top of file $filename\n"; 200 if(open(my $displayfh, "<", "$filename")) { 201 my $line = <$displayfh>; 202 print "$line"; 203 close $displayfh; 204 } 205 print "=== End of file $filename\n"; 206 } 207 208 209 #*************************************************************************** 210 # Display contents of the ssh daemon config file 211 # 212 sub display_sshdconfig { 213 display_file($sshdconfig); 214 } 215 216 217 #*************************************************************************** 218 # Display contents of the ssh client config file 219 # 220 sub display_sshconfig { 221 display_file($sshconfig); 222 } 223 224 225 #*************************************************************************** 226 # Display contents of the sftp client config file 227 # 228 sub display_sftpconfig { 229 display_file($sftpconfig); 230 } 231 232 233 #*************************************************************************** 234 # Display contents of the ssh daemon log file 235 # 236 sub display_sshdlog { 237 die "error: \$sshdlog uninitialized" if(not defined $sshdlog); 238 display_file($sshdlog); 239 } 240 241 242 #*************************************************************************** 243 # Display contents of the ssh client log file 244 # 245 sub display_sshlog { 246 die "error: \$sshlog uninitialized" if(not defined $sshlog); 247 display_file($sshlog); 248 } 249 250 251 #*************************************************************************** 252 # Display contents of the sftp client log file 253 # 254 sub display_sftplog { 255 die "error: \$sftplog uninitialized" if(not defined $sftplog); 256 display_file($sftplog); 257 } 258 259 260 #*************************************************************************** 261 # Find a file somewhere in the given path 262 # 263 sub find_file { 264 my $fn = $_[0]; 265 shift; 266 my @path = @_; 267 foreach (@path) { 268 my $file = File::Spec->catfile($_, $fn); 269 if(-e $file && ! -d $file) { 270 return $file; 271 } 272 } 273 return ""; 274 } 275 276 277 #*************************************************************************** 278 # Find an executable file somewhere in the given path 279 # 280 sub find_exe_file { 281 my $fn = $_[0]; 282 shift; 283 my @path = @_; 284 my $xext = exe_ext('SSH'); 285 foreach (@path) { 286 my $file = File::Spec->catfile($_, $fn); 287 if(-e $file && ! -d $file) { 288 return $file if(-x $file); 289 return $file if(($xext) && (lc($file) =~ /\Q$xext\E$/)); 290 } 291 } 292 return ""; 293 } 294 295 296 #*************************************************************************** 297 # Find a file in environment path or in our sftppath 298 # 299 sub find_file_spath { 300 my $filename = $_[0]; 301 my @spath; 302 push(@spath, File::Spec->path()); 303 push(@spath, @sftppath); 304 return find_file($filename, @spath); 305 } 306 307 308 #*************************************************************************** 309 # Find an executable file in environment path or in our httptlssrvpath 310 # 311 sub find_exe_file_hpath { 312 my $filename = $_[0]; 313 my @hpath; 314 push(@hpath, File::Spec->path()); 315 push(@hpath, @httptlssrvpath); 316 return find_exe_file($filename, @hpath); 317 } 318 319 320 #*************************************************************************** 321 # Find ssh daemon and return canonical filename 322 # 323 sub find_sshd { 324 return find_file_spath($sshdexe); 325 } 326 327 328 #*************************************************************************** 329 # Find ssh client and return canonical filename 330 # 331 sub find_ssh { 332 return find_file_spath($sshexe); 333 } 334 335 336 #*************************************************************************** 337 # Find sftp-server plugin and return canonical filename 338 # 339 sub find_sftpsrv { 340 return find_file_spath($sftpsrvexe); 341 } 342 343 344 #*************************************************************************** 345 # Find sftp client and return canonical filename 346 # 347 sub find_sftp { 348 return find_file_spath($sftpexe); 349 } 350 351 352 #*************************************************************************** 353 # Find ssh-keygen and return canonical filename 354 # 355 sub find_sshkeygen { 356 return find_file_spath($sshkeygenexe); 357 } 358 359 360 #*************************************************************************** 361 # Find httptlssrv (gnutls-serv) and return canonical filename 362 # 363 sub find_httptlssrv { 364 my $p = find_exe_file_hpath($httptlssrvexe); 365 if($p) { 366 my @o = `"$p" -l`; 367 my $found; 368 for(@o) { 369 if(/Key exchange: SRP/) { 370 $found = 1; 371 last; 372 } 373 } 374 return $p if($found); 375 } 376 return ""; 377 } 378 379 380 #*************************************************************************** 381 # Return version info for the given ssh client or server binaries 382 # 383 sub sshversioninfo { 384 my $sshbin = $_[0]; # canonical filename 385 my $major; 386 my $minor; 387 my $patch; 388 my $sshid; 389 my $versnum; 390 my $versstr; 391 my $error; 392 393 if(!$sshbin) { 394 $error = 'Error: Missing argument 1 for sshversioninfo()'; 395 } 396 elsif(! -x $sshbin) { 397 $error = "Error: cannot read or execute $sshbin"; 398 } 399 else { 400 my $cmd = ($sshbin =~ /$sshdexe$/) ? "\"$sshbin\" -?" : "\"$sshbin\" -V"; 401 $error = "$cmd\n"; 402 foreach my $tmpstr (qx($cmd 2>&1)) { 403 if($tmpstr =~ /OpenSSH[_-](\d+)\.(\d+)(\.(\d+))*/i) { 404 $major = $1; 405 $minor = $2; 406 $patch = $4?$4:0; 407 $sshid = 'OpenSSH'; 408 $versnum = (100*$major) + (10*$minor) + $patch; 409 $versstr = "$sshid $major.$minor.$patch"; 410 $error = undef; 411 last; 412 } 413 if($tmpstr =~ /OpenSSH[_-]for[_-]Windows[_-](\d+)\.(\d+)(\.(\d+))*/i) { 414 $major = $1; 415 $minor = $2; 416 $patch = $4?$4:0; 417 $sshid = 'OpenSSH-Windows'; 418 $versnum = (100*$major) + (10*$minor) + $patch; 419 $versstr = "$sshid $major.$minor.$patch"; 420 $error = undef; 421 last; 422 } 423 if($tmpstr =~ /Sun[_-]SSH[_-](\d+)\.(\d+)(\.(\d+))*/i) { 424 $major = $1; 425 $minor = $2; 426 $patch = $4?$4:0; 427 $sshid = 'SunSSH'; 428 $versnum = (100*$major) + (10*$minor) + $patch; 429 $versstr = "$sshid $major.$minor.$patch"; 430 $error = undef; 431 last; 432 } 433 $error .= $tmpstr; 434 } 435 chomp $error if($error); 436 } 437 return ($sshid, $versnum, $versstr, $error); 438 } 439 440 441 #*************************************************************************** 442 # End of library 443 1;