sshserver.pl 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222
  1. #!/usr/bin/env perl
  2. #***************************************************************************
  3. # _ _ ____ _
  4. # Project ___| | | | _ \| |
  5. # / __| | | | |_) | |
  6. # | (__| |_| | _ <| |___
  7. # \___|\___/|_| \_\_____|
  8. #
  9. # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  10. #
  11. # This software is licensed as described in the file COPYING, which
  12. # you should have received as part of this distribution. The terms
  13. # are also available at https://curl.se/docs/copyright.html.
  14. #
  15. # You may opt to use, copy, modify, merge, publish, distribute and/or sell
  16. # copies of the Software, and permit persons to whom the Software is
  17. # furnished to do so, under the terms of the COPYING file.
  18. #
  19. # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  20. # KIND, either express or implied.
  21. #
  22. # SPDX-License-Identifier: curl
  23. #
  24. #***************************************************************************
  25. # Starts sshd for use in the SCP and SFTP curl test harness tests.
  26. # Also creates the ssh configuration files needed for these tests.
  27. use strict;
  28. use warnings;
  29. use Cwd;
  30. use Cwd 'abs_path';
  31. use Digest::MD5;
  32. use Digest::MD5 'md5_hex';
  33. use Digest::SHA;
  34. use Digest::SHA 'sha256_base64';
  35. use MIME::Base64;
  36. use File::Basename;
  37. #***************************************************************************
  38. # Variables and subs imported from sshhelp module
  39. #
  40. use sshhelp qw(
  41. $sshdexe
  42. $sshexe
  43. $sftpsrvexe
  44. $sftpexe
  45. $sshkeygenexe
  46. $sshdconfig
  47. $sshconfig
  48. $sftpconfig
  49. $knownhosts
  50. $sshdlog
  51. $sshlog
  52. $sftplog
  53. $sftpcmds
  54. $hstprvkeyf
  55. $hstpubkeyf
  56. $hstpubmd5f
  57. $hstpubsha256f
  58. $cliprvkeyf
  59. $clipubkeyf
  60. display_sshdconfig
  61. display_sshconfig
  62. display_sftpconfig
  63. display_sshdlog
  64. display_sshlog
  65. display_sftplog
  66. dump_array
  67. find_sshd
  68. find_ssh
  69. find_sftpsrv
  70. find_sftp
  71. find_sshkeygen
  72. sshversioninfo
  73. );
  74. #***************************************************************************
  75. # Subs imported from serverhelp module
  76. #
  77. use serverhelp qw(
  78. $logfile
  79. server_pidfilename
  80. server_logfilename
  81. );
  82. use pathhelp;
  83. #***************************************************************************
  84. my $verbose = 0; # set to 1 for debugging
  85. my $debugprotocol = 0; # set to 1 for protocol debugging
  86. my $port = 8999; # our default SCP/SFTP server port
  87. my $listenaddr = '127.0.0.1'; # default address on which to listen
  88. my $ipvnum = 4; # default IP version of listener address
  89. my $idnum = 1; # default ssh daemon instance number
  90. my $proto = 'ssh'; # protocol the ssh daemon speaks
  91. my $path = getcwd(); # current working directory
  92. my $logdir = $path .'/log'; # directory for log files
  93. my $piddir; # directory for server config files
  94. my $username = $ENV{USER}; # default user
  95. my $pidfile; # ssh daemon pid file
  96. my $identity = 'curl_client_key'; # default identity file
  97. my $error;
  98. my @cfgarr;
  99. #***************************************************************************
  100. # Returns a path of the given file name in the log directory (PiddirPath)
  101. #
  102. sub pp {
  103. my $file = $_[0];
  104. return "$piddir/$file";
  105. # TODO: do Windows path conversion here
  106. }
  107. #***************************************************************************
  108. # Save the message to the log and print it
  109. sub logmsg {
  110. my $msg = $_[0];
  111. serverhelp::logmsg $msg;
  112. print $msg;
  113. }
  114. #***************************************************************************
  115. # Parse command line options
  116. #
  117. while(@ARGV) {
  118. if($ARGV[0] eq '--verbose') {
  119. $verbose = 1;
  120. }
  121. elsif($ARGV[0] eq '--debugprotocol') {
  122. $verbose = 1;
  123. $debugprotocol = 1;
  124. }
  125. elsif($ARGV[0] eq '--user') {
  126. if($ARGV[1]) {
  127. $username = $ARGV[1];
  128. shift @ARGV;
  129. }
  130. }
  131. elsif($ARGV[0] eq '--id') {
  132. if($ARGV[1]) {
  133. if($ARGV[1] =~ /^(\d+)$/) {
  134. $idnum = $1 if($1 > 0);
  135. shift @ARGV;
  136. }
  137. }
  138. }
  139. elsif($ARGV[0] eq '--ipv4') {
  140. $ipvnum = 4;
  141. $listenaddr = '127.0.0.1' if($listenaddr eq '::1');
  142. }
  143. elsif($ARGV[0] eq '--ipv6') {
  144. $ipvnum = 6;
  145. $listenaddr = '::1' if($listenaddr eq '127.0.0.1');
  146. }
  147. elsif($ARGV[0] eq '--addr') {
  148. if($ARGV[1]) {
  149. my $tmpstr = $ARGV[1];
  150. if($tmpstr =~ /^(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)$/) {
  151. $listenaddr = "$1.$2.$3.$4" if($ipvnum == 4);
  152. shift @ARGV;
  153. }
  154. elsif($ipvnum == 6) {
  155. $listenaddr = $tmpstr;
  156. $listenaddr =~ s/^\[(.*)\]$/$1/;
  157. shift @ARGV;
  158. }
  159. }
  160. }
  161. elsif($ARGV[0] eq '--pidfile') {
  162. if($ARGV[1]) {
  163. $pidfile = "$path/". $ARGV[1];
  164. shift @ARGV;
  165. }
  166. }
  167. elsif($ARGV[0] eq '--logdir') {
  168. if($ARGV[1]) {
  169. $logdir = "$path/". $ARGV[1];
  170. shift @ARGV;
  171. }
  172. }
  173. elsif($ARGV[0] eq '--sshport') {
  174. if($ARGV[1]) {
  175. if($ARGV[1] =~ /^(\d+)$/) {
  176. $port = $1;
  177. shift @ARGV;
  178. }
  179. }
  180. }
  181. else {
  182. print STDERR "\nWarning: sshserver.pl unknown parameter: $ARGV[0]\n";
  183. }
  184. shift @ARGV;
  185. }
  186. #***************************************************************************
  187. # Initialize command line option dependent variables
  188. #
  189. #***************************************************************************
  190. # Default ssh daemon pid file name & directory
  191. #
  192. if($pidfile) {
  193. # Use our pidfile directory to store server config files
  194. $piddir = dirname($pidfile);
  195. }
  196. else {
  197. # Use the current directory to store server config files
  198. $piddir = $path;
  199. $pidfile = server_pidfilename($piddir, $proto, $ipvnum, $idnum);
  200. }
  201. #***************************************************************************
  202. # ssh and sftp server log file names
  203. #
  204. $sshdlog = server_logfilename($logdir, 'ssh', $ipvnum, $idnum);
  205. $sftplog = server_logfilename($logdir, 'sftp', $ipvnum, $idnum);
  206. $logfile = "$logdir/sshserver.log"; # used by logmsg
  207. #***************************************************************************
  208. # Logging level for ssh server and client
  209. #
  210. my $loglevel = $debugprotocol?'DEBUG3':'DEBUG2';
  211. #***************************************************************************
  212. # Validate username
  213. #
  214. if(!$username) {
  215. $error = 'Will not run ssh server without a user name';
  216. }
  217. elsif($username eq 'root') {
  218. $error = 'Will not run ssh server as root to mitigate security risks';
  219. }
  220. if($error) {
  221. logmsg "$error\n";
  222. exit 1;
  223. }
  224. #***************************************************************************
  225. # Find out ssh daemon canonical file name
  226. #
  227. my $sshd = find_sshd();
  228. if(!$sshd) {
  229. logmsg "cannot find $sshdexe\n";
  230. exit 1;
  231. }
  232. #***************************************************************************
  233. # Find out ssh daemon version info
  234. #
  235. my ($sshdid, $sshdvernum, $sshdverstr, $sshderror) = sshversioninfo($sshd);
  236. if(!$sshdid) {
  237. # Not an OpenSSH or SunSSH ssh daemon
  238. logmsg "$sshderror\n" if($verbose);
  239. logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n";
  240. exit 1;
  241. }
  242. logmsg "ssh server found $sshd is $sshdverstr\n" if($verbose);
  243. #***************************************************************************
  244. # ssh daemon command line options we might use and version support
  245. #
  246. # -e: log stderr : OpenSSH 2.9.0 and later
  247. # -f: sshd config file : OpenSSH 1.2.1 and later
  248. # -D: no daemon forking : OpenSSH 2.5.0 and later
  249. # -o: command-line option : OpenSSH 3.1.0 and later
  250. # -t: test config file : OpenSSH 2.9.9 and later
  251. # -?: sshd version info : OpenSSH 1.2.1 and later
  252. #
  253. # -e: log stderr : SunSSH 1.0.0 and later
  254. # -f: sshd config file : SunSSH 1.0.0 and later
  255. # -D: no daemon forking : SunSSH 1.0.0 and later
  256. # -o: command-line option : SunSSH 1.0.0 and later
  257. # -t: test config file : SunSSH 1.0.0 and later
  258. # -?: sshd version info : SunSSH 1.0.0 and later
  259. #***************************************************************************
  260. # Verify minimum ssh daemon version
  261. #
  262. if((($sshdid =~ /OpenSSH/) && ($sshdvernum < 299)) ||
  263. (($sshdid =~ /SunSSH/) && ($sshdvernum < 100))) {
  264. logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n";
  265. exit 1;
  266. }
  267. #***************************************************************************
  268. # Find out sftp server plugin canonical file name
  269. #
  270. my $sftpsrv = find_sftpsrv();
  271. if(!$sftpsrv) {
  272. logmsg "cannot find $sftpsrvexe\n";
  273. exit 1;
  274. }
  275. logmsg "sftp server plugin found $sftpsrv\n" if($verbose);
  276. #***************************************************************************
  277. # Find out sftp client canonical file name
  278. #
  279. my $sftp = find_sftp();
  280. if(!$sftp) {
  281. logmsg "cannot find $sftpexe\n";
  282. exit 1;
  283. }
  284. logmsg "sftp client found $sftp\n" if($verbose);
  285. #***************************************************************************
  286. # Find out ssh keygen canonical file name
  287. #
  288. my $sshkeygen = find_sshkeygen();
  289. if(!$sshkeygen) {
  290. logmsg "cannot find $sshkeygenexe\n";
  291. exit 1;
  292. }
  293. logmsg "ssh keygen found $sshkeygen\n" if($verbose);
  294. #***************************************************************************
  295. # Find out ssh client canonical file name
  296. #
  297. my $ssh = find_ssh();
  298. if(!$ssh) {
  299. logmsg "cannot find $sshexe\n";
  300. exit 1;
  301. }
  302. #***************************************************************************
  303. # Find out ssh client version info
  304. #
  305. my ($sshid, $sshvernum, $sshverstr, $ssherror) = sshversioninfo($ssh);
  306. if(!$sshid) {
  307. # Not an OpenSSH or SunSSH ssh client
  308. logmsg "$ssherror\n" if($verbose);
  309. logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n";
  310. exit 1;
  311. }
  312. logmsg "ssh client found $ssh is $sshverstr\n" if($verbose);
  313. #***************************************************************************
  314. # ssh client command line options we might use and version support
  315. #
  316. # -D: dynamic app port forwarding : OpenSSH 2.9.9 and later
  317. # -F: ssh config file : OpenSSH 2.9.9 and later
  318. # -N: no shell/command : OpenSSH 2.1.0 and later
  319. # -p: connection port : OpenSSH 1.2.1 and later
  320. # -v: verbose messages : OpenSSH 1.2.1 and later
  321. # -vv: increase verbosity : OpenSSH 2.3.0 and later
  322. # -V: ssh version info : OpenSSH 1.2.1 and later
  323. #
  324. # -D: dynamic app port forwarding : SunSSH 1.0.0 and later
  325. # -F: ssh config file : SunSSH 1.0.0 and later
  326. # -N: no shell/command : SunSSH 1.0.0 and later
  327. # -p: connection port : SunSSH 1.0.0 and later
  328. # -v: verbose messages : SunSSH 1.0.0 and later
  329. # -vv: increase verbosity : SunSSH 1.0.0 and later
  330. # -V: ssh version info : SunSSH 1.0.0 and later
  331. #***************************************************************************
  332. # Verify minimum ssh client version
  333. #
  334. if((($sshid =~ /OpenSSH/) && ($sshvernum < 299)) ||
  335. (($sshid =~ /SunSSH/) && ($sshvernum < 100))) {
  336. logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n";
  337. exit 1;
  338. }
  339. #***************************************************************************
  340. # ssh keygen command line options we actually use and version support
  341. #
  342. # -C: identity comment : OpenSSH 1.2.1 and later
  343. # -f: key filename : OpenSSH 1.2.1 and later
  344. # -N: new passphrase : OpenSSH 1.2.1 and later
  345. # -q: quiet keygen : OpenSSH 1.2.1 and later
  346. # -t: key type : OpenSSH 2.5.0 and later
  347. #
  348. # -C: identity comment : SunSSH 1.0.0 and later
  349. # -f: key filename : SunSSH 1.0.0 and later
  350. # -N: new passphrase : SunSSH 1.0.0 and later
  351. # -q: quiet keygen : SunSSH 1.0.0 and later
  352. # -t: key type : SunSSH 1.0.0 and later
  353. $sshdconfig = pp($sshdconfig);
  354. $sshconfig = pp($sshconfig);
  355. $sftpconfig = pp($sftpconfig);
  356. #***************************************************************************
  357. # Generate host and client key files for curl's tests
  358. #
  359. if((! -e pp($hstprvkeyf)) || (! -s pp($hstprvkeyf)) ||
  360. (! -e pp($hstpubkeyf)) || (! -s pp($hstpubkeyf)) ||
  361. (! -e pp($hstpubmd5f)) || (! -s pp($hstpubmd5f)) ||
  362. (! -e pp($hstpubsha256f)) || (! -s pp($hstpubsha256f)) ||
  363. (! -e pp($cliprvkeyf)) || (! -s pp($cliprvkeyf)) ||
  364. (! -e pp($clipubkeyf)) || (! -s pp($clipubkeyf))) {
  365. # Make sure all files are gone so ssh-keygen doesn't complain
  366. unlink(pp($hstprvkeyf), pp($hstpubkeyf), pp($hstpubmd5f),
  367. pp($hstpubsha256f), pp($cliprvkeyf), pp($clipubkeyf));
  368. logmsg "generating host keys...\n" if($verbose);
  369. if(system "\"$sshkeygen\" -q -t rsa -f " . pp($hstprvkeyf) . " -C 'curl test server' -N ''") {
  370. logmsg "Could not generate host key\n";
  371. exit 1;
  372. }
  373. logmsg "generating client keys...\n" if($verbose);
  374. if(system "\"$sshkeygen\" -q -t rsa -f " . pp($cliprvkeyf) . " -C 'curl test client' -N ''") {
  375. logmsg "Could not generate client key\n";
  376. exit 1;
  377. }
  378. # Make sure that permissions are restricted so openssh doesn't complain
  379. system "chmod 600 " . pp($hstprvkeyf);
  380. system "chmod 600 " . pp($cliprvkeyf);
  381. if(pathhelp::os_is_win()) {
  382. # https://ss64.com/nt/icacls.html
  383. $ENV{'MSYS2_ARG_CONV_EXCL'} = '/reset';
  384. system("icacls \"" . pathhelp::sys_native_abs_path(pp($hstprvkeyf)) . "\" /reset");
  385. system("icacls \"" . pathhelp::sys_native_abs_path(pp($hstprvkeyf)) . "\" /grant:r \"$username:(R)\"");
  386. system("icacls \"" . pathhelp::sys_native_abs_path(pp($hstprvkeyf)) . "\" /inheritance:r");
  387. }
  388. # Save md5 and sha256 hashes of public host key
  389. open(my $rsakeyfile, "<", pp($hstpubkeyf));
  390. my @rsahostkey = do { local $/ = ' '; <$rsakeyfile> };
  391. close($rsakeyfile);
  392. if(!$rsahostkey[1]) {
  393. logmsg "Failed parsing base64 encoded RSA host key\n";
  394. exit 1;
  395. }
  396. open(my $pubmd5file, ">", pp($hstpubmd5f));
  397. print $pubmd5file md5_hex(decode_base64($rsahostkey[1]));
  398. close($pubmd5file);
  399. if((! -e pp($hstpubmd5f)) || (! -s pp($hstpubmd5f))) {
  400. logmsg "Failed writing md5 hash of RSA host key\n";
  401. exit 1;
  402. }
  403. open(my $pubsha256file, ">", pp($hstpubsha256f));
  404. print $pubsha256file sha256_base64(decode_base64($rsahostkey[1]));
  405. close($pubsha256file);
  406. if((! -e pp($hstpubsha256f)) || (! -s pp($hstpubsha256f))) {
  407. logmsg "Failed writing sha256 hash of RSA host key\n";
  408. exit 1;
  409. }
  410. }
  411. #***************************************************************************
  412. # Convert paths for curl's tests running on Windows with Cygwin/MSYS OpenSSH
  413. #
  414. my $clipubkeyf_config;
  415. my $hstprvkeyf_config;
  416. my $pidfile_config;
  417. my $sftpsrv_config;
  418. my $sshdconfig_abs;
  419. if ($sshdid =~ /OpenSSH-Windows/) {
  420. # Ensure to use native Windows paths with OpenSSH for Windows
  421. $clipubkeyf_config = pathhelp::sys_native_abs_path(pp($clipubkeyf));
  422. $hstprvkeyf_config = pathhelp::sys_native_abs_path(pp($hstprvkeyf));
  423. $pidfile_config = pathhelp::sys_native_abs_path($pidfile);
  424. $sftpsrv_config = pathhelp::sys_native_abs_path($sftpsrv);
  425. $sshdconfig_abs = pathhelp::sys_native_abs_path($sshdconfig);
  426. }
  427. elsif (pathhelp::os_is_win()) {
  428. # Ensure to use MinGW/Cygwin paths
  429. $clipubkeyf_config = pathhelp::build_sys_abs_path(pp($clipubkeyf));
  430. $hstprvkeyf_config = pathhelp::build_sys_abs_path(pp($hstprvkeyf));
  431. $pidfile_config = pathhelp::build_sys_abs_path($pidfile);
  432. $sftpsrv_config = "internal-sftp";
  433. $sshdconfig_abs = pathhelp::build_sys_abs_path($sshdconfig);
  434. }
  435. else {
  436. $clipubkeyf_config = abs_path(pp($clipubkeyf));
  437. $hstprvkeyf_config = abs_path(pp($hstprvkeyf));
  438. $pidfile_config = $pidfile;
  439. $sftpsrv_config = $sftpsrv;
  440. $sshdconfig_abs = abs_path($sshdconfig);
  441. }
  442. #***************************************************************************
  443. # ssh daemon configuration file options we might use and version support
  444. #
  445. # AFSTokenPassing : OpenSSH 1.2.1 and later [1]
  446. # AddressFamily : OpenSSH 4.0.0 and later
  447. # AllowTcpForwarding : OpenSSH 2.3.0 and later
  448. # AllowUsers : OpenSSH 1.2.1 and later
  449. # AuthorizedKeysFile : OpenSSH 2.9.9 and later
  450. # AuthorizedKeysFile2 : OpenSSH 2.9.9 till 5.9
  451. # Banner : OpenSSH 2.5.0 and later
  452. # ChallengeResponseAuthentication : OpenSSH 2.5.0 and later
  453. # Ciphers : OpenSSH 2.1.0 and later [3]
  454. # ClientAliveCountMax : OpenSSH 2.9.0 and later
  455. # ClientAliveInterval : OpenSSH 2.9.0 and later
  456. # Compression : OpenSSH 3.3.0 and later
  457. # DenyUsers : OpenSSH 1.2.1 and later
  458. # ForceCommand : OpenSSH 4.4.0 and later [3]
  459. # GatewayPorts : OpenSSH 2.1.0 and later
  460. # GSSAPIAuthentication : OpenSSH 3.7.0 and later [1]
  461. # GSSAPICleanupCredentials : OpenSSH 3.8.0 and later [1]
  462. # GSSAPIKeyExchange : SunSSH 1.0.0 and later [1]
  463. # GSSAPIStoreDelegatedCredentials : SunSSH 1.0.0 and later [1]
  464. # GSSCleanupCreds : SunSSH 1.0.0 and later [1]
  465. # GSSUseSessionCredCache : SunSSH 1.0.0 and later [1]
  466. # HostbasedAuthentication : OpenSSH 2.9.0 and later
  467. # HostbasedUsesNameFromPacketOnly : OpenSSH 2.9.0 and later
  468. # HostKey : OpenSSH 1.2.1 and later
  469. # IgnoreRhosts : OpenSSH 1.2.1 and later
  470. # IgnoreUserKnownHosts : OpenSSH 1.2.1 and later
  471. # KbdInteractiveAuthentication : OpenSSH 2.3.0 and later
  472. # KeepAlive : OpenSSH 1.2.1 and later
  473. # KerberosAuthentication : OpenSSH 1.2.1 and later [1]
  474. # KerberosGetAFSToken : OpenSSH 3.8.0 and later [1]
  475. # KerberosOrLocalPasswd : OpenSSH 1.2.1 and later [1]
  476. # KerberosTgtPassing : OpenSSH 1.2.1 and later [1]
  477. # KerberosTicketCleanup : OpenSSH 1.2.1 and later [1]
  478. # KeyRegenerationInterval : OpenSSH 1.2.1 till 7.3
  479. # ListenAddress : OpenSSH 1.2.1 and later
  480. # LoginGraceTime : OpenSSH 1.2.1 and later
  481. # LogLevel : OpenSSH 1.2.1 and later
  482. # LookupClientHostnames : SunSSH 1.0.0 and later
  483. # MACs : OpenSSH 2.5.0 and later [3]
  484. # Match : OpenSSH 4.4.0 and later [3]
  485. # MaxAuthTries : OpenSSH 3.9.0 and later
  486. # MaxStartups : OpenSSH 2.2.0 and later
  487. # PAMAuthenticationViaKbdInt : OpenSSH 2.9.0 and later [2]
  488. # PasswordAuthentication : OpenSSH 1.2.1 and later
  489. # PermitEmptyPasswords : OpenSSH 1.2.1 and later
  490. # PermitOpen : OpenSSH 4.4.0 and later [3]
  491. # PermitRootLogin : OpenSSH 1.2.1 and later
  492. # PermitTunnel : OpenSSH 4.3.0 and later
  493. # PermitUserEnvironment : OpenSSH 3.5.0 and later
  494. # PidFile : OpenSSH 2.1.0 and later
  495. # Port : OpenSSH 1.2.1 and later
  496. # PrintLastLog : OpenSSH 2.9.0 and later
  497. # PrintMotd : OpenSSH 1.2.1 and later
  498. # Protocol : OpenSSH 2.1.0 and later
  499. # PubkeyAuthentication : OpenSSH 2.5.0 and later
  500. # RhostsAuthentication : OpenSSH 1.2.1 and later
  501. # RhostsRSAAuthentication : OpenSSH 1.2.1 till 7.3
  502. # RSAAuthentication : OpenSSH 1.2.1 till 7.3
  503. # ServerKeyBits : OpenSSH 1.2.1 till 7.3
  504. # SkeyAuthentication : OpenSSH 1.2.1 and later [1]
  505. # StrictModes : OpenSSH 1.2.1 and later
  506. # Subsystem : OpenSSH 2.2.0 and later
  507. # SyslogFacility : OpenSSH 1.2.1 and later
  508. # TCPKeepAlive : OpenSSH 3.8.0 and later
  509. # UseDNS : OpenSSH 3.7.0 and later
  510. # UseLogin : OpenSSH 1.2.1 till 7.3
  511. # UsePAM : OpenSSH 3.7.0 and later [1][2]
  512. # UsePrivilegeSeparation : OpenSSH 3.2.2 and later
  513. # VerifyReverseMapping : OpenSSH 3.1.0 and later
  514. # X11DisplayOffset : OpenSSH 1.2.1 and later [3]
  515. # X11Forwarding : OpenSSH 1.2.1 and later
  516. # X11UseLocalhost : OpenSSH 3.1.0 and later
  517. # XAuthLocation : OpenSSH 2.1.1 and later [3]
  518. #
  519. # [1] Option only available if activated at compile time
  520. # [2] Option specific for portable versions
  521. # [3] Option not used in our ssh server config file
  522. #***************************************************************************
  523. # Initialize sshd config with options actually supported in OpenSSH 2.9.9
  524. #
  525. logmsg "generating ssh server config file...\n" if($verbose);
  526. @cfgarr = ();
  527. push @cfgarr, '# This is a generated file. Do not edit.';
  528. push @cfgarr, "# $sshdverstr sshd configuration file for curl testing";
  529. push @cfgarr, '#';
  530. # AllowUsers and DenyUsers options should use lowercase on Windows
  531. # and do not support quotes around values for some unknown reason.
  532. if ($sshdid =~ /OpenSSH-Windows/) {
  533. my $username_lc = lc $username;
  534. push @cfgarr, "AllowUsers " . $username_lc =~ s/ /\?/gr;
  535. if (exists $ENV{USERDOMAIN}) {
  536. my $userdomain_lc = lc $ENV{USERDOMAIN};
  537. $username_lc = "$userdomain_lc\\$username_lc";
  538. $username_lc =~ s/ /\?/g; # replace space with ?
  539. push @cfgarr, "AllowUsers " . $username_lc =~ s/ /\?/gr;
  540. }
  541. } else {
  542. push @cfgarr, "AllowUsers $username";
  543. }
  544. push @cfgarr, "AuthorizedKeysFile $clipubkeyf_config";
  545. if(!($sshdid =~ /OpenSSH/) || ($sshdvernum <= 730)) {
  546. push @cfgarr, "AuthorizedKeysFile2 $clipubkeyf_config";
  547. }
  548. push @cfgarr, "HostKey $hstprvkeyf_config";
  549. if ($sshdid !~ /OpenSSH-Windows/) {
  550. push @cfgarr, "PidFile $pidfile_config";
  551. push @cfgarr, '#';
  552. }
  553. if(($sshdid =~ /OpenSSH/) && ($sshdvernum >= 880)) {
  554. push @cfgarr, 'HostKeyAlgorithms +ssh-rsa';
  555. push @cfgarr, 'PubkeyAcceptedKeyTypes +ssh-rsa';
  556. }
  557. push @cfgarr, '#';
  558. push @cfgarr, "Port $port";
  559. push @cfgarr, "ListenAddress $listenaddr";
  560. push @cfgarr, 'Protocol 2';
  561. push @cfgarr, '#';
  562. push @cfgarr, 'AllowTcpForwarding yes';
  563. push @cfgarr, 'Banner none';
  564. push @cfgarr, 'ChallengeResponseAuthentication no';
  565. push @cfgarr, 'ClientAliveCountMax 3';
  566. push @cfgarr, 'ClientAliveInterval 0';
  567. push @cfgarr, 'GatewayPorts no';
  568. push @cfgarr, 'HostbasedAuthentication no';
  569. push @cfgarr, 'HostbasedUsesNameFromPacketOnly no';
  570. push @cfgarr, 'IgnoreRhosts yes';
  571. push @cfgarr, 'IgnoreUserKnownHosts yes';
  572. push @cfgarr, 'LoginGraceTime 30';
  573. push @cfgarr, "LogLevel $loglevel";
  574. push @cfgarr, 'MaxStartups 5';
  575. push @cfgarr, 'PasswordAuthentication no';
  576. push @cfgarr, 'PermitEmptyPasswords no';
  577. push @cfgarr, 'PermitRootLogin no';
  578. push @cfgarr, 'PrintLastLog no';
  579. push @cfgarr, 'PrintMotd no';
  580. push @cfgarr, 'PubkeyAuthentication yes';
  581. push @cfgarr, 'StrictModes no';
  582. push @cfgarr, "Subsystem sftp \"$sftpsrv_config\"";
  583. push @cfgarr, 'SyslogFacility AUTH';
  584. if(!($sshdid =~ /OpenSSH/) || ($sshdvernum <= 730)) {
  585. push @cfgarr, 'KeyRegenerationInterval 0';
  586. push @cfgarr, 'RhostsRSAAuthentication no';
  587. push @cfgarr, 'RSAAuthentication no';
  588. push @cfgarr, 'ServerKeyBits 768';
  589. push @cfgarr, 'UseLogin no';
  590. }
  591. push @cfgarr, 'X11Forwarding no';
  592. push @cfgarr, '#';
  593. #***************************************************************************
  594. # Write out initial sshd configuration file for curl's tests
  595. #
  596. $error = dump_array($sshdconfig, @cfgarr);
  597. if($error) {
  598. logmsg "$error\n";
  599. exit 1;
  600. }
  601. #***************************************************************************
  602. # Verifies at run time if sshd supports a given configuration file option
  603. #
  604. sub sshd_supports_opt {
  605. my ($option, $value) = @_;
  606. my $err;
  607. #
  608. if((($sshdid =~ /OpenSSH/) && ($sshdvernum >= 310)) ||
  609. ($sshdid =~ /SunSSH/)) {
  610. # ssh daemon supports command line options -t -f and -o
  611. $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/,
  612. `\"$sshd\" -t -f $sshdconfig_abs -o \"$option=$value\" 2>&1`;
  613. return !$err;
  614. }
  615. if(($sshdid =~ /OpenSSH/) && ($sshdvernum >= 299)) {
  616. # ssh daemon supports command line options -t and -f
  617. $err = dump_array($sshdconfig, (@cfgarr, "$option $value"));
  618. if($err) {
  619. logmsg "$err\n";
  620. return 0;
  621. }
  622. $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/,
  623. `\"$sshd\" -t -f $sshdconfig_abs 2>&1`;
  624. unlink $sshdconfig;
  625. return !$err;
  626. }
  627. return 0;
  628. }
  629. #***************************************************************************
  630. # Kerberos Authentication support may have not been built into sshd
  631. #
  632. if(sshd_supports_opt('KerberosAuthentication','no')) {
  633. push @cfgarr, 'KerberosAuthentication no';
  634. }
  635. if(sshd_supports_opt('KerberosGetAFSToken','no')) {
  636. push @cfgarr, 'KerberosGetAFSToken no';
  637. }
  638. if(sshd_supports_opt('KerberosOrLocalPasswd','no')) {
  639. push @cfgarr, 'KerberosOrLocalPasswd no';
  640. }
  641. if(sshd_supports_opt('KerberosTgtPassing','no')) {
  642. push @cfgarr, 'KerberosTgtPassing no';
  643. }
  644. if(sshd_supports_opt('KerberosTicketCleanup','yes')) {
  645. push @cfgarr, 'KerberosTicketCleanup yes';
  646. }
  647. #***************************************************************************
  648. # Andrew File System support may have not been built into sshd
  649. #
  650. if(sshd_supports_opt('AFSTokenPassing','no')) {
  651. push @cfgarr, 'AFSTokenPassing no';
  652. }
  653. #***************************************************************************
  654. # S/Key authentication support may have not been built into sshd
  655. #
  656. if(sshd_supports_opt('SkeyAuthentication','no')) {
  657. push @cfgarr, 'SkeyAuthentication no';
  658. }
  659. #***************************************************************************
  660. # GSSAPI Authentication support may have not been built into sshd
  661. #
  662. my $sshd_builtwith_GSSAPI;
  663. if(sshd_supports_opt('GSSAPIAuthentication','no')) {
  664. push @cfgarr, 'GSSAPIAuthentication no';
  665. $sshd_builtwith_GSSAPI = 1;
  666. }
  667. if(sshd_supports_opt('GSSAPICleanupCredentials','yes')) {
  668. push @cfgarr, 'GSSAPICleanupCredentials yes';
  669. }
  670. if(sshd_supports_opt('GSSAPIKeyExchange','no')) {
  671. push @cfgarr, 'GSSAPIKeyExchange no';
  672. }
  673. if(sshd_supports_opt('GSSAPIStoreDelegatedCredentials','no')) {
  674. push @cfgarr, 'GSSAPIStoreDelegatedCredentials no';
  675. }
  676. if(sshd_supports_opt('GSSCleanupCreds','yes')) {
  677. push @cfgarr, 'GSSCleanupCreds yes';
  678. }
  679. if(sshd_supports_opt('GSSUseSessionCredCache','no')) {
  680. push @cfgarr, 'GSSUseSessionCredCache no';
  681. }
  682. push @cfgarr, '#';
  683. #***************************************************************************
  684. # Options that might be supported or not in sshd OpenSSH 2.9.9 and later
  685. #
  686. if(sshd_supports_opt('AddressFamily','any')) {
  687. # Address family must be specified before ListenAddress
  688. splice @cfgarr, 11, 0, 'AddressFamily any';
  689. }
  690. if(sshd_supports_opt('Compression','no')) {
  691. push @cfgarr, 'Compression no';
  692. }
  693. if(sshd_supports_opt('KbdInteractiveAuthentication','no')) {
  694. push @cfgarr, 'KbdInteractiveAuthentication no';
  695. }
  696. if(sshd_supports_opt('KeepAlive','no')) {
  697. push @cfgarr, 'KeepAlive no';
  698. }
  699. if(sshd_supports_opt('LookupClientHostnames','no')) {
  700. push @cfgarr, 'LookupClientHostnames no';
  701. }
  702. if(sshd_supports_opt('MaxAuthTries','10')) {
  703. push @cfgarr, 'MaxAuthTries 10';
  704. }
  705. if(sshd_supports_opt('PAMAuthenticationViaKbdInt','no')) {
  706. push @cfgarr, 'PAMAuthenticationViaKbdInt no';
  707. }
  708. if(sshd_supports_opt('PermitTunnel','no')) {
  709. push @cfgarr, 'PermitTunnel no';
  710. }
  711. if(sshd_supports_opt('PermitUserEnvironment','no')) {
  712. push @cfgarr, 'PermitUserEnvironment no';
  713. }
  714. if(sshd_supports_opt('RhostsAuthentication','no')) {
  715. push @cfgarr, 'RhostsAuthentication no';
  716. }
  717. if(sshd_supports_opt('TCPKeepAlive','no')) {
  718. push @cfgarr, 'TCPKeepAlive no';
  719. }
  720. if(sshd_supports_opt('UseDNS','no')) {
  721. push @cfgarr, 'UseDNS no';
  722. }
  723. if(sshd_supports_opt('UsePAM','no')) {
  724. push @cfgarr, 'UsePAM no';
  725. }
  726. if($sshdid =~ /OpenSSH/) {
  727. # http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6492415
  728. if(sshd_supports_opt('UsePrivilegeSeparation','no')) {
  729. push @cfgarr, 'UsePrivilegeSeparation no';
  730. }
  731. }
  732. if(sshd_supports_opt('VerifyReverseMapping','no')) {
  733. push @cfgarr, 'VerifyReverseMapping no';
  734. }
  735. if(sshd_supports_opt('X11UseLocalhost','yes')) {
  736. push @cfgarr, 'X11UseLocalhost yes';
  737. }
  738. push @cfgarr, '#';
  739. #***************************************************************************
  740. # Write out resulting sshd configuration file for curl's tests
  741. #
  742. $error = dump_array($sshdconfig, @cfgarr);
  743. if($error) {
  744. logmsg "$error\n";
  745. exit 1;
  746. }
  747. #***************************************************************************
  748. # Verify that sshd actually supports our generated configuration file
  749. #
  750. if(system "\"$sshd\" -t -f $sshdconfig_abs > $sshdlog 2>&1") {
  751. logmsg "sshd configuration file $sshdconfig failed verification\n";
  752. display_sshdlog();
  753. display_sshdconfig();
  754. exit 1;
  755. }
  756. #***************************************************************************
  757. # Generate ssh client host key database file for curl's tests
  758. #
  759. if((! -e pp($knownhosts)) || (! -s pp($knownhosts))) {
  760. logmsg "generating ssh client known hosts file...\n" if($verbose);
  761. unlink(pp($knownhosts));
  762. if(open(my $rsakeyfile, "<", pp($hstpubkeyf))) {
  763. my @rsahostkey = do { local $/ = ' '; <$rsakeyfile> };
  764. if(close($rsakeyfile)) {
  765. if(open(my $knownhostsh, ">", pp($knownhosts))) {
  766. print $knownhostsh "$listenaddr ssh-rsa $rsahostkey[1]\n";
  767. if(!close($knownhostsh)) {
  768. $error = "Error: cannot close file $knownhosts";
  769. }
  770. }
  771. else {
  772. $error = "Error: cannot write file $knownhosts";
  773. }
  774. }
  775. else {
  776. $error = "Error: cannot close file $hstpubkeyf";
  777. }
  778. }
  779. else {
  780. $error = "Error: cannot read file $hstpubkeyf";
  781. }
  782. if($error) {
  783. logmsg "$error\n";
  784. exit 1;
  785. }
  786. }
  787. #***************************************************************************
  788. # Convert paths for curl's tests running on Windows using Cygwin OpenSSH
  789. #
  790. my $identity_config;
  791. my $knownhosts_config;
  792. if ($sshdid =~ /OpenSSH-Windows/) {
  793. # Ensure to use native Windows paths with OpenSSH for Windows
  794. $identity_config = pathhelp::sys_native_abs_path(pp($identity));
  795. $knownhosts_config = pathhelp::sys_native_abs_path(pp($knownhosts));
  796. }
  797. elsif (pathhelp::os_is_win()) {
  798. # Ensure to use MinGW/Cygwin paths
  799. $identity_config = pathhelp::build_sys_abs_path(pp($identity));
  800. $knownhosts_config = pathhelp::build_sys_abs_path(pp($knownhosts));
  801. }
  802. else {
  803. $identity_config = abs_path(pp($identity));
  804. $knownhosts_config = abs_path(pp($knownhosts));
  805. }
  806. #***************************************************************************
  807. # ssh client configuration file options we might use and version support
  808. #
  809. # AddressFamily : OpenSSH 3.7.0 and later
  810. # BatchMode : OpenSSH 1.2.1 and later
  811. # BindAddress : OpenSSH 2.9.9 and later
  812. # ChallengeResponseAuthentication : OpenSSH 2.5.0 and later
  813. # CheckHostIP : OpenSSH 1.2.1 and later
  814. # Cipher : OpenSSH 1.2.1 and later [3]
  815. # Ciphers : OpenSSH 2.1.0 and later [3]
  816. # ClearAllForwardings : OpenSSH 2.9.9 and later
  817. # Compression : OpenSSH 1.2.1 and later
  818. # CompressionLevel : OpenSSH 1.2.1 and later [3]
  819. # ConnectionAttempts : OpenSSH 1.2.1 and later
  820. # ConnectTimeout : OpenSSH 3.7.0 and later
  821. # ControlMaster : OpenSSH 3.9.0 and later
  822. # ControlPath : OpenSSH 3.9.0 and later
  823. # DisableBanner : SunSSH 1.2.0 and later
  824. # DynamicForward : OpenSSH 2.9.0 and later
  825. # EnableSSHKeysign : OpenSSH 3.6.0 and later
  826. # EscapeChar : OpenSSH 1.2.1 and later [3]
  827. # ExitOnForwardFailure : OpenSSH 4.4.0 and later
  828. # ForwardAgent : OpenSSH 1.2.1 and later
  829. # ForwardX11 : OpenSSH 1.2.1 and later
  830. # ForwardX11Trusted : OpenSSH 3.8.0 and later
  831. # GatewayPorts : OpenSSH 1.2.1 and later
  832. # GlobalKnownHostsFile : OpenSSH 1.2.1 and later
  833. # GSSAPIAuthentication : OpenSSH 3.7.0 and later [1]
  834. # GSSAPIDelegateCredentials : OpenSSH 3.7.0 and later [1]
  835. # HashKnownHosts : OpenSSH 4.0.0 and later
  836. # Host : OpenSSH 1.2.1 and later
  837. # HostbasedAuthentication : OpenSSH 2.9.0 and later
  838. # HostKeyAlgorithms : OpenSSH 2.9.0 and later [3]
  839. # HostKeyAlias : OpenSSH 2.5.0 and later [3]
  840. # HostName : OpenSSH 1.2.1 and later
  841. # IdentitiesOnly : OpenSSH 3.9.0 and later
  842. # IdentityFile : OpenSSH 1.2.1 and later
  843. # IgnoreIfUnknown : SunSSH 1.2.0 and later
  844. # KeepAlive : OpenSSH 1.2.1 and later
  845. # KbdInteractiveAuthentication : OpenSSH 2.3.0 and later
  846. # KbdInteractiveDevices : OpenSSH 2.3.0 and later [3]
  847. # LocalCommand : OpenSSH 4.3.0 and later [3]
  848. # LocalForward : OpenSSH 1.2.1 and later [3]
  849. # LogLevel : OpenSSH 1.2.1 and later
  850. # MACs : OpenSSH 2.5.0 and later [3]
  851. # NoHostAuthenticationForLocalhost : OpenSSH 3.0.0 and later
  852. # NumberOfPasswordPrompts : OpenSSH 1.2.1 and later
  853. # PasswordAuthentication : OpenSSH 1.2.1 and later
  854. # PermitLocalCommand : OpenSSH 4.3.0 and later
  855. # Port : OpenSSH 1.2.1 and later
  856. # PreferredAuthentications : OpenSSH 2.5.2 and later
  857. # Protocol : OpenSSH 2.1.0 and later
  858. # ProxyCommand : OpenSSH 1.2.1 and later [3]
  859. # PubkeyAuthentication : OpenSSH 2.5.0 and later
  860. # RekeyLimit : OpenSSH 3.7.0 and later
  861. # RemoteForward : OpenSSH 1.2.1 and later [3]
  862. # RhostsRSAAuthentication : OpenSSH 1.2.1 and later
  863. # RSAAuthentication : OpenSSH 1.2.1 and later
  864. # ServerAliveCountMax : OpenSSH 3.8.0 and later
  865. # ServerAliveInterval : OpenSSH 3.8.0 and later
  866. # SmartcardDevice : OpenSSH 2.9.9 and later [1][3]
  867. # StrictHostKeyChecking : OpenSSH 1.2.1 and later
  868. # TCPKeepAlive : OpenSSH 3.8.0 and later
  869. # Tunnel : OpenSSH 4.3.0 and later
  870. # TunnelDevice : OpenSSH 4.3.0 and later [3]
  871. # UsePAM : OpenSSH 3.7.0 and later [1][2][3]
  872. # UsePrivilegedPort : OpenSSH 1.2.1 and later
  873. # User : OpenSSH 1.2.1 and later
  874. # UserKnownHostsFile : OpenSSH 1.2.1 and later
  875. # VerifyHostKeyDNS : OpenSSH 3.8.0 and later
  876. # XAuthLocation : OpenSSH 2.1.1 and later [3]
  877. #
  878. # [1] Option only available if activated at compile time
  879. # [2] Option specific for portable versions
  880. # [3] Option not used in our ssh client config file
  881. #***************************************************************************
  882. # Initialize ssh config with options actually supported in OpenSSH 2.9.9
  883. #
  884. logmsg "generating ssh client config file...\n" if($verbose);
  885. @cfgarr = ();
  886. push @cfgarr, '# This is a generated file. Do not edit.';
  887. push @cfgarr, "# $sshverstr ssh client configuration file for curl testing";
  888. push @cfgarr, '#';
  889. push @cfgarr, 'Host *';
  890. push @cfgarr, '#';
  891. push @cfgarr, "Port $port";
  892. push @cfgarr, "HostName $listenaddr";
  893. push @cfgarr, "User $username";
  894. push @cfgarr, 'Protocol 2';
  895. push @cfgarr, '#';
  896. # BindAddress option is not supported by OpenSSH for Windows
  897. if (!($sshdid =~ /OpenSSH-Windows/)) {
  898. push @cfgarr, "BindAddress $listenaddr";
  899. }
  900. push @cfgarr, '#';
  901. push @cfgarr, "IdentityFile $identity_config";
  902. push @cfgarr, "UserKnownHostsFile $knownhosts_config";
  903. push @cfgarr, '#';
  904. push @cfgarr, 'BatchMode yes';
  905. push @cfgarr, 'ChallengeResponseAuthentication no';
  906. push @cfgarr, 'CheckHostIP no';
  907. push @cfgarr, 'ClearAllForwardings no';
  908. push @cfgarr, 'Compression no';
  909. push @cfgarr, 'ConnectionAttempts 3';
  910. push @cfgarr, 'ForwardAgent no';
  911. push @cfgarr, 'ForwardX11 no';
  912. push @cfgarr, 'GatewayPorts no';
  913. push @cfgarr, 'GlobalKnownHostsFile /dev/null';
  914. push @cfgarr, 'HostbasedAuthentication no';
  915. push @cfgarr, 'KbdInteractiveAuthentication no';
  916. push @cfgarr, "LogLevel $loglevel";
  917. push @cfgarr, 'NumberOfPasswordPrompts 0';
  918. push @cfgarr, 'PasswordAuthentication no';
  919. push @cfgarr, 'PreferredAuthentications publickey';
  920. push @cfgarr, 'PubkeyAuthentication yes';
  921. # RSA authentication options are not supported by OpenSSH for Windows
  922. if (!($sshdid =~ /OpenSSH-Windows/ || pathhelp::os_is_win())) {
  923. push @cfgarr, 'RhostsRSAAuthentication no';
  924. push @cfgarr, 'RSAAuthentication no';
  925. }
  926. # Disabled StrictHostKeyChecking since it makes the tests fail on my
  927. # OpenSSH_6.0p1 on Debian Linux / Daniel
  928. push @cfgarr, 'StrictHostKeyChecking no';
  929. push @cfgarr, 'UsePrivilegedPort no';
  930. push @cfgarr, '#';
  931. #***************************************************************************
  932. # Options supported in ssh client newer than OpenSSH 2.9.9
  933. #
  934. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) {
  935. push @cfgarr, 'AddressFamily any';
  936. }
  937. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) ||
  938. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  939. push @cfgarr, 'ConnectTimeout 30';
  940. }
  941. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) {
  942. push @cfgarr, 'ControlMaster no';
  943. }
  944. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 420)) {
  945. push @cfgarr, 'ControlPath none';
  946. }
  947. if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) {
  948. push @cfgarr, 'DisableBanner yes';
  949. }
  950. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 360)) {
  951. push @cfgarr, 'EnableSSHKeysign no';
  952. }
  953. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 440)) {
  954. push @cfgarr, 'ExitOnForwardFailure yes';
  955. }
  956. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) ||
  957. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  958. push @cfgarr, 'ForwardX11Trusted no';
  959. }
  960. if(($sshd_builtwith_GSSAPI) && ($sshdid eq $sshid) &&
  961. ($sshdvernum == $sshvernum)) {
  962. push @cfgarr, 'GSSAPIAuthentication no';
  963. push @cfgarr, 'GSSAPIDelegateCredentials no';
  964. if($sshid =~ /SunSSH/) {
  965. push @cfgarr, 'GSSAPIKeyExchange no';
  966. }
  967. }
  968. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 400)) ||
  969. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  970. push @cfgarr, 'HashKnownHosts no';
  971. }
  972. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) {
  973. push @cfgarr, 'IdentitiesOnly yes';
  974. }
  975. if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) {
  976. push @cfgarr, 'IgnoreIfUnknown no';
  977. }
  978. if((($sshid =~ /OpenSSH/) && ($sshvernum < 380)) ||
  979. ($sshid =~ /SunSSH/)) {
  980. push @cfgarr, 'KeepAlive no';
  981. }
  982. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 300)) ||
  983. ($sshid =~ /SunSSH/)) {
  984. push @cfgarr, 'NoHostAuthenticationForLocalhost no';
  985. }
  986. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) {
  987. push @cfgarr, 'PermitLocalCommand no';
  988. }
  989. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) ||
  990. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  991. push @cfgarr, 'RekeyLimit 1G';
  992. }
  993. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) ||
  994. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  995. push @cfgarr, 'ServerAliveCountMax 3';
  996. push @cfgarr, 'ServerAliveInterval 0';
  997. }
  998. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) {
  999. push @cfgarr, 'TCPKeepAlive no';
  1000. }
  1001. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) {
  1002. push @cfgarr, 'Tunnel no';
  1003. }
  1004. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) {
  1005. push @cfgarr, 'VerifyHostKeyDNS no';
  1006. }
  1007. push @cfgarr, '#';
  1008. #***************************************************************************
  1009. # Write out resulting ssh client configuration file for curl's tests
  1010. #
  1011. $error = dump_array($sshconfig, @cfgarr);
  1012. if($error) {
  1013. logmsg "$error\n";
  1014. exit 1;
  1015. }
  1016. #***************************************************************************
  1017. # Initialize client sftp config with options actually supported.
  1018. #
  1019. logmsg "generating sftp client config file...\n" if($verbose);
  1020. splice @cfgarr, 1, 1, "# $sshverstr sftp client configuration file for curl testing";
  1021. #
  1022. for(my $i = scalar(@cfgarr) - 1; $i > 0; $i--) {
  1023. if($cfgarr[$i] =~ /^DynamicForward/) {
  1024. splice @cfgarr, $i, 1;
  1025. next;
  1026. }
  1027. if($cfgarr[$i] =~ /^ClearAllForwardings/) {
  1028. splice @cfgarr, $i, 1, "ClearAllForwardings yes";
  1029. next;
  1030. }
  1031. }
  1032. #***************************************************************************
  1033. # Write out resulting sftp client configuration file for curl's tests
  1034. #
  1035. $error = dump_array($sftpconfig, @cfgarr);
  1036. if($error) {
  1037. logmsg "$error\n";
  1038. exit 1;
  1039. }
  1040. @cfgarr = ();
  1041. #***************************************************************************
  1042. # Generate client sftp commands batch file for sftp server verification
  1043. #
  1044. logmsg "generating sftp client commands file...\n" if($verbose);
  1045. push @cfgarr, 'pwd';
  1046. push @cfgarr, 'quit';
  1047. $error = dump_array(pp($sftpcmds), @cfgarr);
  1048. if($error) {
  1049. logmsg "$error\n";
  1050. exit 1;
  1051. }
  1052. @cfgarr = ();
  1053. #***************************************************************************
  1054. # Prepare command line of ssh server daemon
  1055. #
  1056. my $cmd = "\"$sshd\" -e -D -f $sshdconfig_abs > $sshdlog 2>&1";
  1057. logmsg "SCP/SFTP server listening on port $port\n" if($verbose);
  1058. logmsg "RUN: $cmd\n" if($verbose);
  1059. #***************************************************************************
  1060. # Start the ssh server daemon on Windows without forking it
  1061. #
  1062. if ($sshdid =~ /OpenSSH-Windows/) {
  1063. # Fake pidfile for ssh server on Windows.
  1064. if(open(my $out, ">", "$pidfile")) {
  1065. print $out $$ . "\n";
  1066. close($out);
  1067. }
  1068. # Flush output.
  1069. $| = 1;
  1070. # Put an "exec" in front of the command so that the child process
  1071. # keeps this child's process ID by being tied to the spawned shell.
  1072. exec("exec $cmd") || die "Can't exec() $cmd: $!";
  1073. # exec() will create a new process, but ties the existence of the
  1074. # new process to the parent waiting perl.exe and sh.exe processes.
  1075. # exec() should never return back here to this process. We protect
  1076. # ourselves by calling die() just in case something goes really bad.
  1077. die "error: exec() has returned";
  1078. }
  1079. #***************************************************************************
  1080. # Start the ssh server daemon without forking it
  1081. #
  1082. # "exec" avoids the shell process sticking around
  1083. my $rc = system("exec " . $cmd);
  1084. if($rc == -1) {
  1085. logmsg "\"$sshd\" failed with: $!\n";
  1086. }
  1087. elsif($rc & 127) {
  1088. logmsg sprintf("\"$sshd\" died with signal %d, and %s coredump\n",
  1089. ($rc & 127), ($rc & 128)?'a':'no');
  1090. }
  1091. elsif($verbose && ($rc >> 8)) {
  1092. logmsg sprintf("\"$sshd\" exited with %d\n", $rc >> 8);
  1093. }
  1094. #***************************************************************************
  1095. # Clean up once the server has stopped
  1096. #
  1097. unlink(pp($hstprvkeyf), pp($hstpubkeyf), pp($hstpubmd5f), pp($hstpubsha256f),
  1098. pp($cliprvkeyf), pp($clipubkeyf), pp($knownhosts),
  1099. $sshdconfig, $sshconfig, $sftpconfig);
  1100. exit 0;