sshhelp.pm 12 KB

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