sshserver.pl 42 KB

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