sshserver.pl 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. #!/usr/bin/env perl
  2. #***************************************************************************
  3. # _ _ ____ _
  4. # Project ___| | | | _ \| |
  5. # / __| | | | |_) | |
  6. # | (__| |_| | _ <| |___
  7. # \___|\___/|_| \_\_____|
  8. #
  9. # Copyright (C) 1998 - 2011, 2013, 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 http://curl.haxx.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. #***************************************************************************
  23. # Starts sshd for use in the SCP, SFTP and SOCKS curl test harness tests.
  24. # Also creates the ssh configuration files needed for these tests.
  25. use strict;
  26. use warnings;
  27. use Cwd;
  28. #***************************************************************************
  29. # Variables and subs imported from sshhelp module
  30. #
  31. use sshhelp qw(
  32. $sshdexe
  33. $sshexe
  34. $sftpsrvexe
  35. $sftpexe
  36. $sshkeygenexe
  37. $sshdconfig
  38. $sshconfig
  39. $sftpconfig
  40. $knownhosts
  41. $sshdlog
  42. $sshlog
  43. $sftplog
  44. $sftpcmds
  45. $hstprvkeyf
  46. $hstpubkeyf
  47. $cliprvkeyf
  48. $clipubkeyf
  49. display_sshdconfig
  50. display_sshconfig
  51. display_sftpconfig
  52. display_sshdlog
  53. display_sshlog
  54. display_sftplog
  55. dump_array
  56. find_sshd
  57. find_ssh
  58. find_sftpsrv
  59. find_sftp
  60. find_sshkeygen
  61. logmsg
  62. sshversioninfo
  63. );
  64. #***************************************************************************
  65. # Subs imported from serverhelp module
  66. #
  67. use serverhelp qw(
  68. server_pidfilename
  69. server_logfilename
  70. );
  71. #***************************************************************************
  72. my $verbose = 0; # set to 1 for debugging
  73. my $debugprotocol = 0; # set to 1 for protocol debugging
  74. my $port = 8999; # our default SCP/SFTP server port
  75. my $socksport = $port + 1; # our default SOCKS4/5 server port
  76. my $listenaddr = '127.0.0.1'; # default address on which to listen
  77. my $ipvnum = 4; # default IP version of listener address
  78. my $idnum = 1; # dafault ssh daemon instance number
  79. my $proto = 'ssh'; # protocol the ssh daemon speaks
  80. my $path = getcwd(); # current working directory
  81. my $logdir = $path .'/log'; # directory for log files
  82. my $username = $ENV{USER}; # default user
  83. my $pidfile; # ssh daemon pid file
  84. my $error;
  85. my @cfgarr;
  86. #***************************************************************************
  87. # Parse command line options
  88. #
  89. while(@ARGV) {
  90. if($ARGV[0] eq '--verbose') {
  91. $verbose = 1;
  92. }
  93. elsif($ARGV[0] eq '--debugprotocol') {
  94. $verbose = 1;
  95. $debugprotocol = 1;
  96. }
  97. elsif($ARGV[0] eq '--user') {
  98. if($ARGV[1]) {
  99. $username = $ARGV[1];
  100. shift @ARGV;
  101. }
  102. }
  103. elsif($ARGV[0] eq '--id') {
  104. if($ARGV[1]) {
  105. if($ARGV[1] =~ /^(\d+)$/) {
  106. $idnum = $1 if($1 > 0);
  107. shift @ARGV;
  108. }
  109. }
  110. }
  111. elsif($ARGV[0] eq '--ipv4') {
  112. $ipvnum = 4;
  113. $listenaddr = '127.0.0.1' if($listenaddr eq '::1');
  114. }
  115. elsif($ARGV[0] eq '--ipv6') {
  116. $ipvnum = 6;
  117. $listenaddr = '::1' if($listenaddr eq '127.0.0.1');
  118. }
  119. elsif($ARGV[0] eq '--addr') {
  120. if($ARGV[1]) {
  121. my $tmpstr = $ARGV[1];
  122. if($tmpstr =~ /^(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)$/) {
  123. $listenaddr = "$1.$2.$3.$4" if($ipvnum == 4);
  124. shift @ARGV;
  125. }
  126. elsif($ipvnum == 6) {
  127. $listenaddr = $tmpstr;
  128. $listenaddr =~ s/^\[(.*)\]$/$1/;
  129. shift @ARGV;
  130. }
  131. }
  132. }
  133. elsif($ARGV[0] eq '--pidfile') {
  134. if($ARGV[1]) {
  135. $pidfile = "$path/". $ARGV[1];
  136. shift @ARGV;
  137. }
  138. }
  139. elsif($ARGV[0] eq '--sshport') {
  140. if($ARGV[1]) {
  141. if($ARGV[1] =~ /^(\d+)$/) {
  142. $port = $1;
  143. shift @ARGV;
  144. }
  145. }
  146. }
  147. elsif($ARGV[0] eq '--socksport') {
  148. if($ARGV[1]) {
  149. if($ARGV[1] =~ /^(\d+)$/) {
  150. $socksport = $1;
  151. shift @ARGV;
  152. }
  153. }
  154. }
  155. else {
  156. print STDERR "\nWarning: sshserver.pl unknown parameter: $ARGV[0]\n";
  157. }
  158. shift @ARGV;
  159. }
  160. #***************************************************************************
  161. # Default ssh daemon pid file name
  162. #
  163. if(!$pidfile) {
  164. $pidfile = "$path/". server_pidfilename($proto, $ipvnum, $idnum);
  165. }
  166. #***************************************************************************
  167. # ssh, socks and sftp server log file names
  168. #
  169. $sshdlog = server_logfilename($logdir, 'ssh', $ipvnum, $idnum);
  170. $sftplog = server_logfilename($logdir, 'sftp', $ipvnum, $idnum);
  171. $sshlog = server_logfilename($logdir, 'socks', $ipvnum, $idnum);
  172. #***************************************************************************
  173. # Logging level for ssh server and client
  174. #
  175. my $loglevel = $debugprotocol?'DEBUG3':'DEBUG2';
  176. #***************************************************************************
  177. # Validate username
  178. #
  179. if(!$username) {
  180. $error = 'Will not run ssh server without a user name';
  181. }
  182. elsif($username eq 'root') {
  183. $error = 'Will not run ssh server as root to mitigate security risks';
  184. }
  185. if($error) {
  186. logmsg $error;
  187. exit 1;
  188. }
  189. #***************************************************************************
  190. # Find out ssh daemon canonical file name
  191. #
  192. my $sshd = find_sshd();
  193. if(!$sshd) {
  194. logmsg "cannot find $sshdexe";
  195. exit 1;
  196. }
  197. #***************************************************************************
  198. # Find out ssh daemon version info
  199. #
  200. my ($sshdid, $sshdvernum, $sshdverstr, $sshderror) = sshversioninfo($sshd);
  201. if(!$sshdid) {
  202. # Not an OpenSSH or SunSSH ssh daemon
  203. logmsg $sshderror if($verbose);
  204. logmsg 'SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later';
  205. exit 1;
  206. }
  207. logmsg "ssh server found $sshd is $sshdverstr" if($verbose);
  208. #***************************************************************************
  209. # ssh daemon command line options we might use and version support
  210. #
  211. # -e: log stderr : OpenSSH 2.9.0 and later
  212. # -f: sshd config file : OpenSSH 1.2.1 and later
  213. # -D: no daemon forking : OpenSSH 2.5.0 and later
  214. # -o: command-line option : OpenSSH 3.1.0 and later
  215. # -t: test config file : OpenSSH 2.9.9 and later
  216. # -?: sshd version info : OpenSSH 1.2.1 and later
  217. #
  218. # -e: log stderr : SunSSH 1.0.0 and later
  219. # -f: sshd config file : SunSSH 1.0.0 and later
  220. # -D: no daemon forking : SunSSH 1.0.0 and later
  221. # -o: command-line option : SunSSH 1.0.0 and later
  222. # -t: test config file : SunSSH 1.0.0 and later
  223. # -?: sshd version info : SunSSH 1.0.0 and later
  224. #***************************************************************************
  225. # Verify minimum ssh daemon version
  226. #
  227. if((($sshdid =~ /OpenSSH/) && ($sshdvernum < 299)) ||
  228. (($sshdid =~ /SunSSH/) && ($sshdvernum < 100))) {
  229. logmsg 'SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later';
  230. exit 1;
  231. }
  232. #***************************************************************************
  233. # Find out sftp server plugin canonical file name
  234. #
  235. my $sftpsrv = find_sftpsrv();
  236. if(!$sftpsrv) {
  237. logmsg "cannot find $sftpsrvexe";
  238. exit 1;
  239. }
  240. logmsg "sftp server plugin found $sftpsrv" if($verbose);
  241. #***************************************************************************
  242. # Find out sftp client canonical file name
  243. #
  244. my $sftp = find_sftp();
  245. if(!$sftp) {
  246. logmsg "cannot find $sftpexe";
  247. exit 1;
  248. }
  249. logmsg "sftp client found $sftp" if($verbose);
  250. #***************************************************************************
  251. # Find out ssh keygen canonical file name
  252. #
  253. my $sshkeygen = find_sshkeygen();
  254. if(!$sshkeygen) {
  255. logmsg "cannot find $sshkeygenexe";
  256. exit 1;
  257. }
  258. logmsg "ssh keygen found $sshkeygen" if($verbose);
  259. #***************************************************************************
  260. # Find out ssh client canonical file name
  261. #
  262. my $ssh = find_ssh();
  263. if(!$ssh) {
  264. logmsg "cannot find $sshexe";
  265. exit 1;
  266. }
  267. #***************************************************************************
  268. # Find out ssh client version info
  269. #
  270. my ($sshid, $sshvernum, $sshverstr, $ssherror) = sshversioninfo($ssh);
  271. if(!$sshid) {
  272. # Not an OpenSSH or SunSSH ssh client
  273. logmsg $ssherror if($verbose);
  274. logmsg 'SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later';
  275. exit 1;
  276. }
  277. logmsg "ssh client found $ssh is $sshverstr" if($verbose);
  278. #***************************************************************************
  279. # ssh client command line options we might use and version support
  280. #
  281. # -D: dynamic app port forwarding : OpenSSH 2.9.9 and later
  282. # -F: ssh config file : OpenSSH 2.9.9 and later
  283. # -N: no shell/command : OpenSSH 2.1.0 and later
  284. # -p: connection port : OpenSSH 1.2.1 and later
  285. # -v: verbose messages : OpenSSH 1.2.1 and later
  286. # -vv: increase verbosity : OpenSSH 2.3.0 and later
  287. # -V: ssh version info : OpenSSH 1.2.1 and later
  288. #
  289. # -D: dynamic app port forwarding : SunSSH 1.0.0 and later
  290. # -F: ssh config file : SunSSH 1.0.0 and later
  291. # -N: no shell/command : SunSSH 1.0.0 and later
  292. # -p: connection port : SunSSH 1.0.0 and later
  293. # -v: verbose messages : SunSSH 1.0.0 and later
  294. # -vv: increase verbosity : SunSSH 1.0.0 and later
  295. # -V: ssh version info : SunSSH 1.0.0 and later
  296. #***************************************************************************
  297. # Verify minimum ssh client version
  298. #
  299. if((($sshid =~ /OpenSSH/) && ($sshvernum < 299)) ||
  300. (($sshid =~ /SunSSH/) && ($sshvernum < 100))) {
  301. logmsg 'SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later';
  302. exit 1;
  303. }
  304. #***************************************************************************
  305. # ssh keygen command line options we actually use and version support
  306. #
  307. # -C: identity comment : OpenSSH 1.2.1 and later
  308. # -f: key filename : OpenSSH 1.2.1 and later
  309. # -N: new passphrase : OpenSSH 1.2.1 and later
  310. # -q: quiet keygen : OpenSSH 1.2.1 and later
  311. # -t: key type : OpenSSH 2.5.0 and later
  312. #
  313. # -C: identity comment : SunSSH 1.0.0 and later
  314. # -f: key filename : SunSSH 1.0.0 and later
  315. # -N: new passphrase : SunSSH 1.0.0 and later
  316. # -q: quiet keygen : SunSSH 1.0.0 and later
  317. # -t: key type : SunSSH 1.0.0 and later
  318. #***************************************************************************
  319. # Generate host and client key files for curl's tests
  320. #
  321. if((! -e $hstprvkeyf) || (! -s $hstprvkeyf) ||
  322. (! -e $hstpubkeyf) || (! -s $hstpubkeyf) ||
  323. (! -e $cliprvkeyf) || (! -s $cliprvkeyf) ||
  324. (! -e $clipubkeyf) || (! -s $clipubkeyf)) {
  325. # Make sure all files are gone so ssh-keygen doesn't complain
  326. unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf);
  327. logmsg 'generating host keys...' if($verbose);
  328. if(system "$sshkeygen -q -t dsa -f $hstprvkeyf -C 'curl test server' -N ''") {
  329. logmsg 'Could not generate host key';
  330. exit 1;
  331. }
  332. logmsg 'generating client keys...' if($verbose);
  333. if(system "$sshkeygen -q -t dsa -f $cliprvkeyf -C 'curl test client' -N ''") {
  334. logmsg 'Could not generate client key';
  335. exit 1;
  336. }
  337. }
  338. #***************************************************************************
  339. # ssh daemon configuration file options we might use and version support
  340. #
  341. # AFSTokenPassing : OpenSSH 1.2.1 and later [1]
  342. # AcceptEnv : OpenSSH 3.9.0 and later
  343. # AddressFamily : OpenSSH 4.0.0 and later
  344. # AllowGroups : OpenSSH 1.2.1 and later
  345. # AllowTcpForwarding : OpenSSH 2.3.0 and later
  346. # AllowUsers : OpenSSH 1.2.1 and later
  347. # AuthorizedKeysFile : OpenSSH 2.9.9 and later
  348. # AuthorizedKeysFile2 : OpenSSH 2.9.9 and later
  349. # Banner : OpenSSH 2.5.0 and later
  350. # ChallengeResponseAuthentication : OpenSSH 2.5.0 and later
  351. # Ciphers : OpenSSH 2.1.0 and later [3]
  352. # ClientAliveCountMax : OpenSSH 2.9.0 and later
  353. # ClientAliveInterval : OpenSSH 2.9.0 and later
  354. # Compression : OpenSSH 3.3.0 and later
  355. # DenyGroups : OpenSSH 1.2.1 and later
  356. # DenyUsers : OpenSSH 1.2.1 and later
  357. # ForceCommand : OpenSSH 4.4.0 and later [3]
  358. # GatewayPorts : OpenSSH 2.1.0 and later
  359. # GSSAPIAuthentication : OpenSSH 3.7.0 and later [1]
  360. # GSSAPICleanupCredentials : OpenSSH 3.8.0 and later [1]
  361. # GSSAPIKeyExchange : SunSSH 1.0.0 and later [1]
  362. # GSSAPIStoreDelegatedCredentials : SunSSH 1.0.0 and later [1]
  363. # GSSCleanupCreds : SunSSH 1.0.0 and later [1]
  364. # GSSUseSessionCredCache : SunSSH 1.0.0 and later [1]
  365. # HostbasedAuthentication : OpenSSH 2.9.0 and later
  366. # HostbasedUsesNameFromPacketOnly : OpenSSH 2.9.0 and later
  367. # HostKey : OpenSSH 1.2.1 and later
  368. # IgnoreRhosts : OpenSSH 1.2.1 and later
  369. # IgnoreUserKnownHosts : OpenSSH 1.2.1 and later
  370. # KbdInteractiveAuthentication : OpenSSH 2.3.0 and later
  371. # KeepAlive : OpenSSH 1.2.1 and later
  372. # KerberosAuthentication : OpenSSH 1.2.1 and later [1]
  373. # KerberosGetAFSToken : OpenSSH 3.8.0 and later [1]
  374. # KerberosOrLocalPasswd : OpenSSH 1.2.1 and later [1]
  375. # KerberosTgtPassing : OpenSSH 1.2.1 and later [1]
  376. # KerberosTicketCleanup : OpenSSH 1.2.1 and later [1]
  377. # KeyRegenerationInterval : OpenSSH 1.2.1 and later
  378. # ListenAddress : OpenSSH 1.2.1 and later
  379. # LoginGraceTime : OpenSSH 1.2.1 and later
  380. # LogLevel : OpenSSH 1.2.1 and later
  381. # LookupClientHostnames : SunSSH 1.0.0 and later
  382. # MACs : OpenSSH 2.5.0 and later [3]
  383. # Match : OpenSSH 4.4.0 and later [3]
  384. # MaxAuthTries : OpenSSH 3.9.0 and later
  385. # MaxStartups : OpenSSH 2.2.0 and later
  386. # PAMAuthenticationViaKbdInt : OpenSSH 2.9.0 and later [2]
  387. # PasswordAuthentication : OpenSSH 1.2.1 and later
  388. # PermitEmptyPasswords : OpenSSH 1.2.1 and later
  389. # PermitOpen : OpenSSH 4.4.0 and later [3]
  390. # PermitRootLogin : OpenSSH 1.2.1 and later
  391. # PermitTunnel : OpenSSH 4.3.0 and later
  392. # PermitUserEnvironment : OpenSSH 3.5.0 and later
  393. # PidFile : OpenSSH 2.1.0 and later
  394. # Port : OpenSSH 1.2.1 and later
  395. # PrintLastLog : OpenSSH 2.9.0 and later
  396. # PrintMotd : OpenSSH 1.2.1 and later
  397. # Protocol : OpenSSH 2.1.0 and later
  398. # PubkeyAuthentication : OpenSSH 2.5.0 and later
  399. # RhostsAuthentication : OpenSSH 1.2.1 and later
  400. # RhostsRSAAuthentication : OpenSSH 1.2.1 and later
  401. # RSAAuthentication : OpenSSH 1.2.1 and later
  402. # ServerKeyBits : OpenSSH 1.2.1 and later
  403. # SkeyAuthentication : OpenSSH 1.2.1 and later [1]
  404. # StrictModes : OpenSSH 1.2.1 and later
  405. # Subsystem : OpenSSH 2.2.0 and later
  406. # SyslogFacility : OpenSSH 1.2.1 and later
  407. # TCPKeepAlive : OpenSSH 3.8.0 and later
  408. # UseDNS : OpenSSH 3.7.0 and later
  409. # UseLogin : OpenSSH 1.2.1 and later
  410. # UsePAM : OpenSSH 3.7.0 and later [1][2]
  411. # UsePrivilegeSeparation : OpenSSH 3.2.2 and later
  412. # VerifyReverseMapping : OpenSSH 3.1.0 and later
  413. # X11DisplayOffset : OpenSSH 1.2.1 and later [3]
  414. # X11Forwarding : OpenSSH 1.2.1 and later
  415. # X11UseLocalhost : OpenSSH 3.1.0 and later
  416. # XAuthLocation : OpenSSH 2.1.1 and later [3]
  417. #
  418. # [1] Option only available if activated at compile time
  419. # [2] Option specific for portable versions
  420. # [3] Option not used in our ssh server config file
  421. #***************************************************************************
  422. # Initialize sshd config with options actually supported in OpenSSH 2.9.9
  423. #
  424. logmsg 'generating ssh server config file...' if($verbose);
  425. @cfgarr = ();
  426. push @cfgarr, '# This is a generated file. Do not edit.';
  427. push @cfgarr, "# $sshdverstr sshd configuration file for curl testing";
  428. push @cfgarr, '#';
  429. push @cfgarr, "DenyUsers !$username";
  430. push @cfgarr, "AllowUsers $username";
  431. push @cfgarr, 'DenyGroups';
  432. push @cfgarr, 'AllowGroups';
  433. push @cfgarr, '#';
  434. push @cfgarr, "AuthorizedKeysFile $path/$clipubkeyf";
  435. push @cfgarr, "AuthorizedKeysFile2 $path/$clipubkeyf";
  436. push @cfgarr, "HostKey $path/$hstprvkeyf";
  437. push @cfgarr, "PidFile $pidfile";
  438. push @cfgarr, '#';
  439. push @cfgarr, "Port $port";
  440. push @cfgarr, "ListenAddress $listenaddr";
  441. push @cfgarr, 'Protocol 2';
  442. push @cfgarr, '#';
  443. push @cfgarr, 'AllowTcpForwarding yes';
  444. push @cfgarr, 'Banner none';
  445. push @cfgarr, 'ChallengeResponseAuthentication no';
  446. push @cfgarr, 'ClientAliveCountMax 3';
  447. push @cfgarr, 'ClientAliveInterval 0';
  448. push @cfgarr, 'GatewayPorts no';
  449. push @cfgarr, 'HostbasedAuthentication no';
  450. push @cfgarr, 'HostbasedUsesNameFromPacketOnly no';
  451. push @cfgarr, 'IgnoreRhosts yes';
  452. push @cfgarr, 'IgnoreUserKnownHosts yes';
  453. push @cfgarr, 'KeyRegenerationInterval 0';
  454. push @cfgarr, 'LoginGraceTime 30';
  455. push @cfgarr, "LogLevel $loglevel";
  456. push @cfgarr, 'MaxStartups 5';
  457. push @cfgarr, 'PasswordAuthentication no';
  458. push @cfgarr, 'PermitEmptyPasswords no';
  459. push @cfgarr, 'PermitRootLogin no';
  460. push @cfgarr, 'PrintLastLog no';
  461. push @cfgarr, 'PrintMotd no';
  462. push @cfgarr, 'PubkeyAuthentication yes';
  463. push @cfgarr, 'RhostsRSAAuthentication no';
  464. push @cfgarr, 'RSAAuthentication no';
  465. push @cfgarr, 'ServerKeyBits 768';
  466. push @cfgarr, 'StrictModes no';
  467. push @cfgarr, "Subsystem sftp $sftpsrv";
  468. push @cfgarr, 'SyslogFacility AUTH';
  469. push @cfgarr, 'UseLogin no';
  470. push @cfgarr, 'X11Forwarding no';
  471. push @cfgarr, '#';
  472. #***************************************************************************
  473. # Write out initial sshd configuration file for curl's tests
  474. #
  475. $error = dump_array($sshdconfig, @cfgarr);
  476. if($error) {
  477. logmsg $error;
  478. exit 1;
  479. }
  480. #***************************************************************************
  481. # Verifies at run time if sshd supports a given configuration file option
  482. #
  483. sub sshd_supports_opt {
  484. my ($option, $value) = @_;
  485. my $err;
  486. #
  487. if((($sshdid =~ /OpenSSH/) && ($sshdvernum >= 310)) ||
  488. ($sshdid =~ /SunSSH/)) {
  489. # ssh daemon supports command line options -t -f and -o
  490. $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/,
  491. qx($sshd -t -f $sshdconfig -o $option=$value 2>&1);
  492. return !$err;
  493. }
  494. if(($sshdid =~ /OpenSSH/) && ($sshdvernum >= 299)) {
  495. # ssh daemon supports command line options -t and -f
  496. $err = dump_array($sshdconfig, (@cfgarr, "$option $value"));
  497. if($err) {
  498. logmsg $err;
  499. return 0;
  500. }
  501. $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/,
  502. qx($sshd -t -f $sshdconfig 2>&1);
  503. unlink $sshdconfig;
  504. return !$err;
  505. }
  506. return 0;
  507. }
  508. #***************************************************************************
  509. # Kerberos Authentication support may have not been built into sshd
  510. #
  511. if(sshd_supports_opt('KerberosAuthentication','no')) {
  512. push @cfgarr, 'KerberosAuthentication no';
  513. }
  514. if(sshd_supports_opt('KerberosGetAFSToken','no')) {
  515. push @cfgarr, 'KerberosGetAFSToken no';
  516. }
  517. if(sshd_supports_opt('KerberosOrLocalPasswd','no')) {
  518. push @cfgarr, 'KerberosOrLocalPasswd no';
  519. }
  520. if(sshd_supports_opt('KerberosTgtPassing','no')) {
  521. push @cfgarr, 'KerberosTgtPassing no';
  522. }
  523. if(sshd_supports_opt('KerberosTicketCleanup','yes')) {
  524. push @cfgarr, 'KerberosTicketCleanup yes';
  525. }
  526. #***************************************************************************
  527. # Andrew File System support may have not been built into sshd
  528. #
  529. if(sshd_supports_opt('AFSTokenPassing','no')) {
  530. push @cfgarr, 'AFSTokenPassing no';
  531. }
  532. #***************************************************************************
  533. # S/Key authentication support may have not been built into sshd
  534. #
  535. if(sshd_supports_opt('SkeyAuthentication','no')) {
  536. push @cfgarr, 'SkeyAuthentication no';
  537. }
  538. #***************************************************************************
  539. # GSSAPI Authentication support may have not been built into sshd
  540. #
  541. my $sshd_builtwith_GSSAPI;
  542. if(sshd_supports_opt('GSSAPIAuthentication','no')) {
  543. push @cfgarr, 'GSSAPIAuthentication no';
  544. $sshd_builtwith_GSSAPI = 1;
  545. }
  546. if(sshd_supports_opt('GSSAPICleanupCredentials','yes')) {
  547. push @cfgarr, 'GSSAPICleanupCredentials yes';
  548. }
  549. if(sshd_supports_opt('GSSAPIKeyExchange','no')) {
  550. push @cfgarr, 'GSSAPIKeyExchange no';
  551. }
  552. if(sshd_supports_opt('GSSAPIStoreDelegatedCredentials','no')) {
  553. push @cfgarr, 'GSSAPIStoreDelegatedCredentials no';
  554. }
  555. if(sshd_supports_opt('GSSCleanupCreds','yes')) {
  556. push @cfgarr, 'GSSCleanupCreds yes';
  557. }
  558. if(sshd_supports_opt('GSSUseSessionCredCache','no')) {
  559. push @cfgarr, 'GSSUseSessionCredCache no';
  560. }
  561. push @cfgarr, '#';
  562. #***************************************************************************
  563. # Options that might be supported or not in sshd OpenSSH 2.9.9 and later
  564. #
  565. if(sshd_supports_opt('AcceptEnv','')) {
  566. push @cfgarr, 'AcceptEnv';
  567. }
  568. if(sshd_supports_opt('AddressFamily','any')) {
  569. # Address family must be specified before ListenAddress
  570. splice @cfgarr, 14, 0, 'AddressFamily any';
  571. }
  572. if(sshd_supports_opt('Compression','no')) {
  573. push @cfgarr, 'Compression no';
  574. }
  575. if(sshd_supports_opt('KbdInteractiveAuthentication','no')) {
  576. push @cfgarr, 'KbdInteractiveAuthentication no';
  577. }
  578. if(sshd_supports_opt('KeepAlive','no')) {
  579. push @cfgarr, 'KeepAlive no';
  580. }
  581. if(sshd_supports_opt('LookupClientHostnames','no')) {
  582. push @cfgarr, 'LookupClientHostnames no';
  583. }
  584. if(sshd_supports_opt('MaxAuthTries','10')) {
  585. push @cfgarr, 'MaxAuthTries 10';
  586. }
  587. if(sshd_supports_opt('PAMAuthenticationViaKbdInt','no')) {
  588. push @cfgarr, 'PAMAuthenticationViaKbdInt no';
  589. }
  590. if(sshd_supports_opt('PermitTunnel','no')) {
  591. push @cfgarr, 'PermitTunnel no';
  592. }
  593. if(sshd_supports_opt('PermitUserEnvironment','no')) {
  594. push @cfgarr, 'PermitUserEnvironment no';
  595. }
  596. if(sshd_supports_opt('RhostsAuthentication','no')) {
  597. push @cfgarr, 'RhostsAuthentication no';
  598. }
  599. if(sshd_supports_opt('TCPKeepAlive','no')) {
  600. push @cfgarr, 'TCPKeepAlive no';
  601. }
  602. if(sshd_supports_opt('UseDNS','no')) {
  603. push @cfgarr, 'UseDNS no';
  604. }
  605. if(sshd_supports_opt('UsePAM','no')) {
  606. push @cfgarr, 'UsePAM no';
  607. }
  608. if($sshdid =~ /OpenSSH/) {
  609. # http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6492415
  610. if(sshd_supports_opt('UsePrivilegeSeparation','no')) {
  611. push @cfgarr, 'UsePrivilegeSeparation no';
  612. }
  613. }
  614. if(sshd_supports_opt('VerifyReverseMapping','no')) {
  615. push @cfgarr, 'VerifyReverseMapping no';
  616. }
  617. if(sshd_supports_opt('X11UseLocalhost','yes')) {
  618. push @cfgarr, 'X11UseLocalhost yes';
  619. }
  620. push @cfgarr, '#';
  621. #***************************************************************************
  622. # Write out resulting sshd configuration file for curl's tests
  623. #
  624. $error = dump_array($sshdconfig, @cfgarr);
  625. if($error) {
  626. logmsg $error;
  627. exit 1;
  628. }
  629. #***************************************************************************
  630. # Verify that sshd actually supports our generated configuration file
  631. #
  632. if(system "$sshd -t -f $sshdconfig > $sshdlog 2>&1") {
  633. logmsg "sshd configuration file $sshdconfig failed verification";
  634. display_sshdlog();
  635. display_sshdconfig();
  636. exit 1;
  637. }
  638. #***************************************************************************
  639. # Generate ssh client host key database file for curl's tests
  640. #
  641. if((! -e $knownhosts) || (! -s $knownhosts)) {
  642. logmsg 'generating ssh client known hosts file...' if($verbose);
  643. unlink($knownhosts);
  644. if(open(DSAKEYFILE, "<$hstpubkeyf")) {
  645. my @dsahostkey = do { local $/ = ' '; <DSAKEYFILE> };
  646. if(close(DSAKEYFILE)) {
  647. if(open(KNOWNHOSTS, ">$knownhosts")) {
  648. print KNOWNHOSTS "$listenaddr ssh-dss $dsahostkey[1]\n";
  649. if(!close(KNOWNHOSTS)) {
  650. $error = "Error: cannot close file $knownhosts";
  651. }
  652. }
  653. else {
  654. $error = "Error: cannot write file $knownhosts";
  655. }
  656. }
  657. else {
  658. $error = "Error: cannot close file $hstpubkeyf";
  659. }
  660. }
  661. else {
  662. $error = "Error: cannot read file $hstpubkeyf";
  663. }
  664. if($error) {
  665. logmsg $error;
  666. exit 1;
  667. }
  668. }
  669. #***************************************************************************
  670. # ssh client configuration file options we might use and version support
  671. #
  672. # AddressFamily : OpenSSH 3.7.0 and later
  673. # BatchMode : OpenSSH 1.2.1 and later
  674. # BindAddress : OpenSSH 2.9.9 and later
  675. # ChallengeResponseAuthentication : OpenSSH 2.5.0 and later
  676. # CheckHostIP : OpenSSH 1.2.1 and later
  677. # Cipher : OpenSSH 1.2.1 and later [3]
  678. # Ciphers : OpenSSH 2.1.0 and later [3]
  679. # ClearAllForwardings : OpenSSH 2.9.9 and later
  680. # Compression : OpenSSH 1.2.1 and later
  681. # CompressionLevel : OpenSSH 1.2.1 and later [3]
  682. # ConnectionAttempts : OpenSSH 1.2.1 and later
  683. # ConnectTimeout : OpenSSH 3.7.0 and later
  684. # ControlMaster : OpenSSH 3.9.0 and later
  685. # ControlPath : OpenSSH 3.9.0 and later
  686. # DisableBanner : SunSSH 1.2.0 and later
  687. # DynamicForward : OpenSSH 2.9.0 and later
  688. # EnableSSHKeysign : OpenSSH 3.6.0 and later
  689. # EscapeChar : OpenSSH 1.2.1 and later [3]
  690. # ExitOnForwardFailure : OpenSSH 4.4.0 and later
  691. # ForwardAgent : OpenSSH 1.2.1 and later
  692. # ForwardX11 : OpenSSH 1.2.1 and later
  693. # ForwardX11Trusted : OpenSSH 3.8.0 and later
  694. # GatewayPorts : OpenSSH 1.2.1 and later
  695. # GlobalKnownHostsFile : OpenSSH 1.2.1 and later
  696. # GSSAPIAuthentication : OpenSSH 3.7.0 and later [1]
  697. # GSSAPIDelegateCredentials : OpenSSH 3.7.0 and later [1]
  698. # HashKnownHosts : OpenSSH 4.0.0 and later
  699. # Host : OpenSSH 1.2.1 and later
  700. # HostbasedAuthentication : OpenSSH 2.9.0 and later
  701. # HostKeyAlgorithms : OpenSSH 2.9.0 and later [3]
  702. # HostKeyAlias : OpenSSH 2.5.0 and later [3]
  703. # HostName : OpenSSH 1.2.1 and later
  704. # IdentitiesOnly : OpenSSH 3.9.0 and later
  705. # IdentityFile : OpenSSH 1.2.1 and later
  706. # IgnoreIfUnknown : SunSSH 1.2.0 and later
  707. # KeepAlive : OpenSSH 1.2.1 and later
  708. # KbdInteractiveAuthentication : OpenSSH 2.3.0 and later
  709. # KbdInteractiveDevices : OpenSSH 2.3.0 and later [3]
  710. # LocalCommand : OpenSSH 4.3.0 and later [3]
  711. # LocalForward : OpenSSH 1.2.1 and later [3]
  712. # LogLevel : OpenSSH 1.2.1 and later
  713. # MACs : OpenSSH 2.5.0 and later [3]
  714. # NoHostAuthenticationForLocalhost : OpenSSH 3.0.0 and later
  715. # NumberOfPasswordPrompts : OpenSSH 1.2.1 and later
  716. # PasswordAuthentication : OpenSSH 1.2.1 and later
  717. # PermitLocalCommand : OpenSSH 4.3.0 and later
  718. # Port : OpenSSH 1.2.1 and later
  719. # PreferredAuthentications : OpenSSH 2.5.2 and later
  720. # Protocol : OpenSSH 2.1.0 and later
  721. # ProxyCommand : OpenSSH 1.2.1 and later [3]
  722. # PubkeyAuthentication : OpenSSH 2.5.0 and later
  723. # RekeyLimit : OpenSSH 3.7.0 and later
  724. # RemoteForward : OpenSSH 1.2.1 and later [3]
  725. # RhostsRSAAuthentication : OpenSSH 1.2.1 and later
  726. # RSAAuthentication : OpenSSH 1.2.1 and later
  727. # SendEnv : OpenSSH 3.9.0 and later
  728. # ServerAliveCountMax : OpenSSH 3.8.0 and later
  729. # ServerAliveInterval : OpenSSH 3.8.0 and later
  730. # SmartcardDevice : OpenSSH 2.9.9 and later [1][3]
  731. # StrictHostKeyChecking : OpenSSH 1.2.1 and later
  732. # TCPKeepAlive : OpenSSH 3.8.0 and later
  733. # Tunnel : OpenSSH 4.3.0 and later
  734. # TunnelDevice : OpenSSH 4.3.0 and later [3]
  735. # UsePAM : OpenSSH 3.7.0 and later [1][2][3]
  736. # UsePrivilegedPort : OpenSSH 1.2.1 and later
  737. # User : OpenSSH 1.2.1 and later
  738. # UserKnownHostsFile : OpenSSH 1.2.1 and later
  739. # VerifyHostKeyDNS : OpenSSH 3.8.0 and later
  740. # XAuthLocation : OpenSSH 2.1.1 and later [3]
  741. #
  742. # [1] Option only available if activated at compile time
  743. # [2] Option specific for portable versions
  744. # [3] Option not used in our ssh client config file
  745. #***************************************************************************
  746. # Initialize ssh config with options actually supported in OpenSSH 2.9.9
  747. #
  748. logmsg 'generating ssh client config file...' if($verbose);
  749. @cfgarr = ();
  750. push @cfgarr, '# This is a generated file. Do not edit.';
  751. push @cfgarr, "# $sshverstr ssh client configuration file for curl testing";
  752. push @cfgarr, '#';
  753. push @cfgarr, 'Host *';
  754. push @cfgarr, '#';
  755. push @cfgarr, "Port $port";
  756. push @cfgarr, "HostName $listenaddr";
  757. push @cfgarr, "User $username";
  758. push @cfgarr, 'Protocol 2';
  759. push @cfgarr, '#';
  760. push @cfgarr, "BindAddress $listenaddr";
  761. push @cfgarr, "DynamicForward $socksport";
  762. push @cfgarr, '#';
  763. push @cfgarr, "IdentityFile $path/curl_client_key";
  764. push @cfgarr, "UserKnownHostsFile $path/$knownhosts";
  765. push @cfgarr, '#';
  766. push @cfgarr, 'BatchMode yes';
  767. push @cfgarr, 'ChallengeResponseAuthentication no';
  768. push @cfgarr, 'CheckHostIP no';
  769. push @cfgarr, 'ClearAllForwardings no';
  770. push @cfgarr, 'Compression no';
  771. push @cfgarr, 'ConnectionAttempts 3';
  772. push @cfgarr, 'ForwardAgent no';
  773. push @cfgarr, 'ForwardX11 no';
  774. push @cfgarr, 'GatewayPorts no';
  775. push @cfgarr, 'GlobalKnownHostsFile /dev/null';
  776. push @cfgarr, 'HostbasedAuthentication no';
  777. push @cfgarr, 'KbdInteractiveAuthentication no';
  778. push @cfgarr, "LogLevel $loglevel";
  779. push @cfgarr, 'NumberOfPasswordPrompts 0';
  780. push @cfgarr, 'PasswordAuthentication no';
  781. push @cfgarr, 'PreferredAuthentications publickey';
  782. push @cfgarr, 'PubkeyAuthentication yes';
  783. push @cfgarr, 'RhostsRSAAuthentication no';
  784. push @cfgarr, 'RSAAuthentication no';
  785. # Disabled StrictHostKeyChecking since it makes the tests fail on my
  786. # OpenSSH_6.0p1 on Debian Linux / Daniel
  787. push @cfgarr, 'StrictHostKeyChecking no';
  788. push @cfgarr, 'UsePrivilegedPort no';
  789. push @cfgarr, '#';
  790. #***************************************************************************
  791. # Options supported in ssh client newer than OpenSSH 2.9.9
  792. #
  793. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) {
  794. push @cfgarr, 'AddressFamily any';
  795. }
  796. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) ||
  797. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  798. push @cfgarr, 'ConnectTimeout 30';
  799. }
  800. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) {
  801. push @cfgarr, 'ControlMaster no';
  802. }
  803. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 420)) {
  804. push @cfgarr, 'ControlPath none';
  805. }
  806. if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) {
  807. push @cfgarr, 'DisableBanner yes';
  808. }
  809. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 360)) {
  810. push @cfgarr, 'EnableSSHKeysign no';
  811. }
  812. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 440)) {
  813. push @cfgarr, 'ExitOnForwardFailure yes';
  814. }
  815. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) ||
  816. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  817. push @cfgarr, 'ForwardX11Trusted no';
  818. }
  819. if(($sshd_builtwith_GSSAPI) && ($sshdid eq $sshid) &&
  820. ($sshdvernum == $sshvernum)) {
  821. push @cfgarr, 'GSSAPIAuthentication no';
  822. push @cfgarr, 'GSSAPIDelegateCredentials no';
  823. if($sshid =~ /SunSSH/) {
  824. push @cfgarr, 'GSSAPIKeyExchange no';
  825. }
  826. }
  827. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 400)) ||
  828. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  829. push @cfgarr, 'HashKnownHosts no';
  830. }
  831. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) {
  832. push @cfgarr, 'IdentitiesOnly yes';
  833. }
  834. if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) {
  835. push @cfgarr, 'IgnoreIfUnknown no';
  836. }
  837. if((($sshid =~ /OpenSSH/) && ($sshvernum < 380)) ||
  838. ($sshid =~ /SunSSH/)) {
  839. push @cfgarr, 'KeepAlive no';
  840. }
  841. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 300)) ||
  842. ($sshid =~ /SunSSH/)) {
  843. push @cfgarr, 'NoHostAuthenticationForLocalhost no';
  844. }
  845. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) {
  846. push @cfgarr, 'PermitLocalCommand no';
  847. }
  848. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) ||
  849. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  850. push @cfgarr, 'RekeyLimit 1G';
  851. }
  852. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) {
  853. push @cfgarr, 'SendEnv';
  854. }
  855. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) ||
  856. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  857. push @cfgarr, 'ServerAliveCountMax 3';
  858. push @cfgarr, 'ServerAliveInterval 0';
  859. }
  860. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) {
  861. push @cfgarr, 'TCPKeepAlive no';
  862. }
  863. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) {
  864. push @cfgarr, 'Tunnel no';
  865. }
  866. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) {
  867. push @cfgarr, 'VerifyHostKeyDNS no';
  868. }
  869. push @cfgarr, '#';
  870. #***************************************************************************
  871. # Write out resulting ssh client configuration file for curl's tests
  872. #
  873. $error = dump_array($sshconfig, @cfgarr);
  874. if($error) {
  875. logmsg $error;
  876. exit 1;
  877. }
  878. #***************************************************************************
  879. # Initialize client sftp config with options actually supported.
  880. #
  881. logmsg 'generating sftp client config file...' if($verbose);
  882. splice @cfgarr, 1, 1, "# $sshverstr sftp client configuration file for curl testing";
  883. #
  884. for(my $i = scalar(@cfgarr) - 1; $i > 0; $i--) {
  885. if($cfgarr[$i] =~ /^DynamicForward/) {
  886. splice @cfgarr, $i, 1;
  887. next;
  888. }
  889. if($cfgarr[$i] =~ /^ClearAllForwardings/) {
  890. splice @cfgarr, $i, 1, "ClearAllForwardings yes";
  891. next;
  892. }
  893. }
  894. #***************************************************************************
  895. # Write out resulting sftp client configuration file for curl's tests
  896. #
  897. $error = dump_array($sftpconfig, @cfgarr);
  898. if($error) {
  899. logmsg $error;
  900. exit 1;
  901. }
  902. @cfgarr = ();
  903. #***************************************************************************
  904. # Generate client sftp commands batch file for sftp server verification
  905. #
  906. logmsg 'generating sftp client commands file...' if($verbose);
  907. push @cfgarr, 'pwd';
  908. push @cfgarr, 'quit';
  909. $error = dump_array($sftpcmds, @cfgarr);
  910. if($error) {
  911. logmsg $error;
  912. exit 1;
  913. }
  914. @cfgarr = ();
  915. #***************************************************************************
  916. # Start the ssh server daemon without forking it
  917. #
  918. logmsg "SCP/SFTP server listening on port $port" if($verbose);
  919. my $rc = system "$sshd -e -D -f $sshdconfig > $sshdlog 2>&1";
  920. if($rc == -1) {
  921. logmsg "$sshd failed with: $!";
  922. }
  923. elsif($rc & 127) {
  924. logmsg sprintf("$sshd died with signal %d, and %s coredump",
  925. ($rc & 127), ($rc & 128)?'a':'no');
  926. }
  927. elsif($verbose && ($rc >> 8)) {
  928. logmsg sprintf("$sshd exited with %d", $rc >> 8);
  929. }
  930. #***************************************************************************
  931. # Clean up once the server has stopped
  932. #
  933. unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf, $knownhosts);
  934. unlink($sshdconfig, $sshconfig, $sftpconfig);
  935. exit 0;