2
0

sshserver.pl 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  1. #!/usr/bin/env perl
  2. #***************************************************************************
  3. # _ _ ____ _
  4. # Project ___| | | | _ \| |
  5. # / __| | | | |_) | |
  6. # | (__| |_| | _ <| |___
  7. # \___|\___/|_| \_\_____|
  8. #
  9. # Copyright (C) 1998 - 2010, 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) || (! -e $hstpubkeyf) ||
  322. (! -e $cliprvkeyf) || (! -e $clipubkeyf)) {
  323. # Make sure all files are gone so ssh-keygen doesn't complain
  324. unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf);
  325. logmsg 'generating host keys...' if($verbose);
  326. if(system "$sshkeygen -q -t dsa -f $hstprvkeyf -C 'curl test server' -N ''") {
  327. logmsg 'Could not generate host key';
  328. exit 1;
  329. }
  330. logmsg 'generating client keys...' if($verbose);
  331. if(system "$sshkeygen -q -t dsa -f $cliprvkeyf -C 'curl test client' -N ''") {
  332. logmsg 'Could not generate client key';
  333. exit 1;
  334. }
  335. }
  336. #***************************************************************************
  337. # ssh daemon configuration file options we might use and version support
  338. #
  339. # AFSTokenPassing : OpenSSH 1.2.1 and later [1]
  340. # AcceptEnv : OpenSSH 3.9.0 and later
  341. # AddressFamily : OpenSSH 4.0.0 and later
  342. # AllowGroups : OpenSSH 1.2.1 and later
  343. # AllowTcpForwarding : OpenSSH 2.3.0 and later
  344. # AllowUsers : OpenSSH 1.2.1 and later
  345. # AuthorizedKeysFile : OpenSSH 2.9.9 and later
  346. # AuthorizedKeysFile2 : OpenSSH 2.9.9 and later
  347. # Banner : OpenSSH 2.5.0 and later
  348. # ChallengeResponseAuthentication : OpenSSH 2.5.0 and later
  349. # Ciphers : OpenSSH 2.1.0 and later [3]
  350. # ClientAliveCountMax : OpenSSH 2.9.0 and later
  351. # ClientAliveInterval : OpenSSH 2.9.0 and later
  352. # Compression : OpenSSH 3.3.0 and later
  353. # DenyGroups : OpenSSH 1.2.1 and later
  354. # DenyUsers : OpenSSH 1.2.1 and later
  355. # ForceCommand : OpenSSH 4.4.0 and later [3]
  356. # GatewayPorts : OpenSSH 2.1.0 and later
  357. # GSSAPIAuthentication : OpenSSH 3.7.0 and later [1]
  358. # GSSAPICleanupCredentials : OpenSSH 3.8.0 and later [1]
  359. # GSSAPIKeyExchange : SunSSH 1.0.0 and later [1]
  360. # GSSAPIStoreDelegatedCredentials : SunSSH 1.0.0 and later [1]
  361. # GSSCleanupCreds : SunSSH 1.0.0 and later [1]
  362. # GSSUseSessionCredCache : SunSSH 1.0.0 and later [1]
  363. # HostbasedAuthentication : OpenSSH 2.9.0 and later
  364. # HostbasedUsesNameFromPacketOnly : OpenSSH 2.9.0 and later
  365. # HostKey : OpenSSH 1.2.1 and later
  366. # IgnoreRhosts : OpenSSH 1.2.1 and later
  367. # IgnoreUserKnownHosts : OpenSSH 1.2.1 and later
  368. # KbdInteractiveAuthentication : OpenSSH 2.3.0 and later
  369. # KeepAlive : OpenSSH 1.2.1 and later
  370. # KerberosAuthentication : OpenSSH 1.2.1 and later [1]
  371. # KerberosGetAFSToken : OpenSSH 3.8.0 and later [1]
  372. # KerberosOrLocalPasswd : OpenSSH 1.2.1 and later [1]
  373. # KerberosTgtPassing : OpenSSH 1.2.1 and later [1]
  374. # KerberosTicketCleanup : OpenSSH 1.2.1 and later [1]
  375. # KeyRegenerationInterval : OpenSSH 1.2.1 and later
  376. # ListenAddress : OpenSSH 1.2.1 and later
  377. # LoginGraceTime : OpenSSH 1.2.1 and later
  378. # LogLevel : OpenSSH 1.2.1 and later
  379. # LookupClientHostnames : SunSSH 1.0.0 and later
  380. # MACs : OpenSSH 2.5.0 and later [3]
  381. # Match : OpenSSH 4.4.0 and later [3]
  382. # MaxAuthTries : OpenSSH 3.9.0 and later
  383. # MaxStartups : OpenSSH 2.2.0 and later
  384. # PAMAuthenticationViaKbdInt : OpenSSH 2.9.0 and later [2]
  385. # PasswordAuthentication : OpenSSH 1.2.1 and later
  386. # PermitEmptyPasswords : OpenSSH 1.2.1 and later
  387. # PermitOpen : OpenSSH 4.4.0 and later [3]
  388. # PermitRootLogin : OpenSSH 1.2.1 and later
  389. # PermitTunnel : OpenSSH 4.3.0 and later
  390. # PermitUserEnvironment : OpenSSH 3.5.0 and later
  391. # PidFile : OpenSSH 2.1.0 and later
  392. # Port : OpenSSH 1.2.1 and later
  393. # PrintLastLog : OpenSSH 2.9.0 and later
  394. # PrintMotd : OpenSSH 1.2.1 and later
  395. # Protocol : OpenSSH 2.1.0 and later
  396. # PubkeyAuthentication : OpenSSH 2.5.0 and later
  397. # RhostsAuthentication : OpenSSH 1.2.1 and later
  398. # RhostsRSAAuthentication : OpenSSH 1.2.1 and later
  399. # RSAAuthentication : OpenSSH 1.2.1 and later
  400. # ServerKeyBits : OpenSSH 1.2.1 and later
  401. # SkeyAuthentication : OpenSSH 1.2.1 and later [1]
  402. # StrictModes : OpenSSH 1.2.1 and later
  403. # Subsystem : OpenSSH 2.2.0 and later
  404. # SyslogFacility : OpenSSH 1.2.1 and later
  405. # TCPKeepAlive : OpenSSH 3.8.0 and later
  406. # UseDNS : OpenSSH 3.7.0 and later
  407. # UseLogin : OpenSSH 1.2.1 and later
  408. # UsePAM : OpenSSH 3.7.0 and later [1][2]
  409. # UsePrivilegeSeparation : OpenSSH 3.2.2 and later
  410. # VerifyReverseMapping : OpenSSH 3.1.0 and later
  411. # X11DisplayOffset : OpenSSH 1.2.1 and later [3]
  412. # X11Forwarding : OpenSSH 1.2.1 and later
  413. # X11UseLocalhost : OpenSSH 3.1.0 and later
  414. # XAuthLocation : OpenSSH 2.1.1 and later [3]
  415. #
  416. # [1] Option only available if activated at compile time
  417. # [2] Option specific for portable versions
  418. # [3] Option not used in our ssh server config file
  419. #***************************************************************************
  420. # Initialize sshd config with options actually supported in OpenSSH 2.9.9
  421. #
  422. logmsg 'generating ssh server config file...' if($verbose);
  423. @cfgarr = ();
  424. push @cfgarr, '# This is a generated file. Do not edit.';
  425. push @cfgarr, "# $sshdverstr sshd configuration file for curl testing";
  426. push @cfgarr, '#';
  427. push @cfgarr, "DenyUsers !$username";
  428. push @cfgarr, "AllowUsers $username";
  429. push @cfgarr, 'DenyGroups';
  430. push @cfgarr, 'AllowGroups';
  431. push @cfgarr, '#';
  432. push @cfgarr, "AuthorizedKeysFile $path/$clipubkeyf";
  433. push @cfgarr, "AuthorizedKeysFile2 $path/$clipubkeyf";
  434. push @cfgarr, "HostKey $path/$hstprvkeyf";
  435. push @cfgarr, "PidFile $pidfile";
  436. push @cfgarr, '#';
  437. push @cfgarr, "Port $port";
  438. push @cfgarr, "ListenAddress $listenaddr";
  439. push @cfgarr, 'Protocol 2';
  440. push @cfgarr, '#';
  441. push @cfgarr, 'AllowTcpForwarding yes';
  442. push @cfgarr, 'Banner none';
  443. push @cfgarr, 'ChallengeResponseAuthentication no';
  444. push @cfgarr, 'ClientAliveCountMax 3';
  445. push @cfgarr, 'ClientAliveInterval 0';
  446. push @cfgarr, 'GatewayPorts no';
  447. push @cfgarr, 'HostbasedAuthentication no';
  448. push @cfgarr, 'HostbasedUsesNameFromPacketOnly no';
  449. push @cfgarr, 'IgnoreRhosts yes';
  450. push @cfgarr, 'IgnoreUserKnownHosts yes';
  451. push @cfgarr, 'KeyRegenerationInterval 0';
  452. push @cfgarr, 'LoginGraceTime 30';
  453. push @cfgarr, "LogLevel $loglevel";
  454. push @cfgarr, 'MaxStartups 5';
  455. push @cfgarr, 'PasswordAuthentication no';
  456. push @cfgarr, 'PermitEmptyPasswords no';
  457. push @cfgarr, 'PermitRootLogin no';
  458. push @cfgarr, 'PrintLastLog no';
  459. push @cfgarr, 'PrintMotd no';
  460. push @cfgarr, 'PubkeyAuthentication yes';
  461. push @cfgarr, 'RhostsRSAAuthentication no';
  462. push @cfgarr, 'RSAAuthentication no';
  463. push @cfgarr, 'ServerKeyBits 768';
  464. push @cfgarr, 'StrictModes no';
  465. push @cfgarr, "Subsystem sftp $sftpsrv";
  466. push @cfgarr, 'SyslogFacility AUTH';
  467. push @cfgarr, 'UseLogin no';
  468. push @cfgarr, 'X11Forwarding no';
  469. push @cfgarr, '#';
  470. #***************************************************************************
  471. # Write out initial sshd configuration file for curl's tests
  472. #
  473. $error = dump_array($sshdconfig, @cfgarr);
  474. if($error) {
  475. logmsg $error;
  476. exit 1;
  477. }
  478. #***************************************************************************
  479. # Verifies at run time if sshd supports a given configuration file option
  480. #
  481. sub sshd_supports_opt {
  482. my ($option, $value) = @_;
  483. my $err;
  484. #
  485. if((($sshdid =~ /OpenSSH/) && ($sshdvernum >= 310)) ||
  486. ($sshdid =~ /SunSSH/)) {
  487. # ssh daemon supports command line options -t -f and -o
  488. $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/,
  489. qx($sshd -t -f $sshdconfig -o $option=$value 2>&1);
  490. return !$err;
  491. }
  492. if(($sshdid =~ /OpenSSH/) && ($sshdvernum >= 299)) {
  493. # ssh daemon supports command line options -t and -f
  494. $err = dump_array($sshdconfig, (@cfgarr, "$option $value"));
  495. if($err) {
  496. logmsg $err;
  497. return 0;
  498. }
  499. $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/,
  500. qx($sshd -t -f $sshdconfig 2>&1);
  501. unlink $sshdconfig;
  502. return !$err;
  503. }
  504. return 0;
  505. }
  506. #***************************************************************************
  507. # Kerberos Authentication support may have not been built into sshd
  508. #
  509. if(sshd_supports_opt('KerberosAuthentication','no')) {
  510. push @cfgarr, 'KerberosAuthentication no';
  511. }
  512. if(sshd_supports_opt('KerberosGetAFSToken','no')) {
  513. push @cfgarr, 'KerberosGetAFSToken no';
  514. }
  515. if(sshd_supports_opt('KerberosOrLocalPasswd','no')) {
  516. push @cfgarr, 'KerberosOrLocalPasswd no';
  517. }
  518. if(sshd_supports_opt('KerberosTgtPassing','no')) {
  519. push @cfgarr, 'KerberosTgtPassing no';
  520. }
  521. if(sshd_supports_opt('KerberosTicketCleanup','yes')) {
  522. push @cfgarr, 'KerberosTicketCleanup yes';
  523. }
  524. #***************************************************************************
  525. # Andrew File System support may have not been built into sshd
  526. #
  527. if(sshd_supports_opt('AFSTokenPassing','no')) {
  528. push @cfgarr, 'AFSTokenPassing no';
  529. }
  530. #***************************************************************************
  531. # S/Key authentication support may have not been built into sshd
  532. #
  533. if(sshd_supports_opt('SkeyAuthentication','no')) {
  534. push @cfgarr, 'SkeyAuthentication no';
  535. }
  536. #***************************************************************************
  537. # GSSAPI Authentication support may have not been built into sshd
  538. #
  539. my $sshd_builtwith_GSSAPI;
  540. if(sshd_supports_opt('GSSAPIAuthentication','no')) {
  541. push @cfgarr, 'GSSAPIAuthentication no';
  542. $sshd_builtwith_GSSAPI = 1;
  543. }
  544. if(sshd_supports_opt('GSSAPICleanupCredentials','yes')) {
  545. push @cfgarr, 'GSSAPICleanupCredentials yes';
  546. }
  547. if(sshd_supports_opt('GSSAPIKeyExchange','no')) {
  548. push @cfgarr, 'GSSAPIKeyExchange no';
  549. }
  550. if(sshd_supports_opt('GSSAPIStoreDelegatedCredentials','no')) {
  551. push @cfgarr, 'GSSAPIStoreDelegatedCredentials no';
  552. }
  553. if(sshd_supports_opt('GSSCleanupCreds','yes')) {
  554. push @cfgarr, 'GSSCleanupCreds yes';
  555. }
  556. if(sshd_supports_opt('GSSUseSessionCredCache','no')) {
  557. push @cfgarr, 'GSSUseSessionCredCache no';
  558. }
  559. push @cfgarr, '#';
  560. #***************************************************************************
  561. # Options that might be supported or not in sshd OpenSSH 2.9.9 and later
  562. #
  563. if(sshd_supports_opt('AcceptEnv','')) {
  564. push @cfgarr, 'AcceptEnv';
  565. }
  566. if(sshd_supports_opt('AddressFamily','any')) {
  567. # Address family must be specified before ListenAddress
  568. splice @cfgarr, 14, 0, 'AddressFamily any';
  569. }
  570. if(sshd_supports_opt('Compression','no')) {
  571. push @cfgarr, 'Compression no';
  572. }
  573. if(sshd_supports_opt('KbdInteractiveAuthentication','no')) {
  574. push @cfgarr, 'KbdInteractiveAuthentication no';
  575. }
  576. if(sshd_supports_opt('KeepAlive','no')) {
  577. push @cfgarr, 'KeepAlive no';
  578. }
  579. if(sshd_supports_opt('LookupClientHostnames','no')) {
  580. push @cfgarr, 'LookupClientHostnames no';
  581. }
  582. if(sshd_supports_opt('MaxAuthTries','10')) {
  583. push @cfgarr, 'MaxAuthTries 10';
  584. }
  585. if(sshd_supports_opt('PAMAuthenticationViaKbdInt','no')) {
  586. push @cfgarr, 'PAMAuthenticationViaKbdInt no';
  587. }
  588. if(sshd_supports_opt('PermitTunnel','no')) {
  589. push @cfgarr, 'PermitTunnel no';
  590. }
  591. if(sshd_supports_opt('PermitUserEnvironment','no')) {
  592. push @cfgarr, 'PermitUserEnvironment no';
  593. }
  594. if(sshd_supports_opt('RhostsAuthentication','no')) {
  595. push @cfgarr, 'RhostsAuthentication no';
  596. }
  597. if(sshd_supports_opt('TCPKeepAlive','no')) {
  598. push @cfgarr, 'TCPKeepAlive no';
  599. }
  600. if(sshd_supports_opt('UseDNS','no')) {
  601. push @cfgarr, 'UseDNS no';
  602. }
  603. if(sshd_supports_opt('UsePAM','no')) {
  604. push @cfgarr, 'UsePAM no';
  605. }
  606. if($sshdid =~ /OpenSSH/) {
  607. # http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6492415
  608. if(sshd_supports_opt('UsePrivilegeSeparation','no')) {
  609. push @cfgarr, 'UsePrivilegeSeparation no';
  610. }
  611. }
  612. if(sshd_supports_opt('VerifyReverseMapping','no')) {
  613. push @cfgarr, 'VerifyReverseMapping no';
  614. }
  615. if(sshd_supports_opt('X11UseLocalhost','yes')) {
  616. push @cfgarr, 'X11UseLocalhost yes';
  617. }
  618. push @cfgarr, '#';
  619. #***************************************************************************
  620. # Write out resulting sshd configuration file for curl's tests
  621. #
  622. $error = dump_array($sshdconfig, @cfgarr);
  623. if($error) {
  624. logmsg $error;
  625. exit 1;
  626. }
  627. #***************************************************************************
  628. # Verify that sshd actually supports our generated configuration file
  629. #
  630. if(system "$sshd -t -f $sshdconfig > $sshdlog 2>&1") {
  631. logmsg "sshd configuration file $sshdconfig failed verification";
  632. display_sshdlog();
  633. display_sshdconfig();
  634. exit 1;
  635. }
  636. #***************************************************************************
  637. # Generate ssh client host key database file for curl's tests
  638. #
  639. if(! -e $knownhosts) {
  640. logmsg 'generating ssh client known hosts file...' if($verbose);
  641. if(open(DSAKEYFILE, "<$hstpubkeyf")) {
  642. my @dsahostkey = do { local $/ = ' '; <DSAKEYFILE> };
  643. if(close(DSAKEYFILE)) {
  644. if(open(KNOWNHOSTS, ">$knownhosts")) {
  645. print KNOWNHOSTS "$listenaddr ssh-dss $dsahostkey[1]\n";
  646. if(!close(KNOWNHOSTS)) {
  647. $error = "Error: cannot close file $knownhosts";
  648. }
  649. }
  650. else {
  651. $error = "Error: cannot write file $knownhosts";
  652. }
  653. }
  654. else {
  655. $error = "Error: cannot close file $hstpubkeyf";
  656. }
  657. }
  658. else {
  659. $error = "Error: cannot read file $hstpubkeyf";
  660. }
  661. if($error) {
  662. logmsg $error;
  663. exit 1;
  664. }
  665. }
  666. #***************************************************************************
  667. # ssh client configuration file options we might use and version support
  668. #
  669. # AddressFamily : OpenSSH 3.7.0 and later
  670. # BatchMode : OpenSSH 1.2.1 and later
  671. # BindAddress : OpenSSH 2.9.9 and later
  672. # ChallengeResponseAuthentication : OpenSSH 2.5.0 and later
  673. # CheckHostIP : OpenSSH 1.2.1 and later
  674. # Cipher : OpenSSH 1.2.1 and later [3]
  675. # Ciphers : OpenSSH 2.1.0 and later [3]
  676. # ClearAllForwardings : OpenSSH 2.9.9 and later
  677. # Compression : OpenSSH 1.2.1 and later
  678. # CompressionLevel : OpenSSH 1.2.1 and later [3]
  679. # ConnectionAttempts : OpenSSH 1.2.1 and later
  680. # ConnectTimeout : OpenSSH 3.7.0 and later
  681. # ControlMaster : OpenSSH 3.9.0 and later
  682. # ControlPath : OpenSSH 3.9.0 and later
  683. # DisableBanner : SunSSH 1.2.0 and later
  684. # DynamicForward : OpenSSH 2.9.0 and later
  685. # EnableSSHKeysign : OpenSSH 3.6.0 and later
  686. # EscapeChar : OpenSSH 1.2.1 and later [3]
  687. # ExitOnForwardFailure : OpenSSH 4.4.0 and later
  688. # ForwardAgent : OpenSSH 1.2.1 and later
  689. # ForwardX11 : OpenSSH 1.2.1 and later
  690. # ForwardX11Trusted : OpenSSH 3.8.0 and later
  691. # GatewayPorts : OpenSSH 1.2.1 and later
  692. # GlobalKnownHostsFile : OpenSSH 1.2.1 and later
  693. # GSSAPIAuthentication : OpenSSH 3.7.0 and later [1]
  694. # GSSAPIDelegateCredentials : OpenSSH 3.7.0 and later [1]
  695. # HashKnownHosts : OpenSSH 4.0.0 and later
  696. # Host : OpenSSH 1.2.1 and later
  697. # HostbasedAuthentication : OpenSSH 2.9.0 and later
  698. # HostKeyAlgorithms : OpenSSH 2.9.0 and later [3]
  699. # HostKeyAlias : OpenSSH 2.5.0 and later [3]
  700. # HostName : OpenSSH 1.2.1 and later
  701. # IdentitiesOnly : OpenSSH 3.9.0 and later
  702. # IdentityFile : OpenSSH 1.2.1 and later
  703. # IgnoreIfUnknown : SunSSH 1.2.0 and later
  704. # KeepAlive : OpenSSH 1.2.1 and later
  705. # KbdInteractiveAuthentication : OpenSSH 2.3.0 and later
  706. # KbdInteractiveDevices : OpenSSH 2.3.0 and later [3]
  707. # LocalCommand : OpenSSH 4.3.0 and later [3]
  708. # LocalForward : OpenSSH 1.2.1 and later [3]
  709. # LogLevel : OpenSSH 1.2.1 and later
  710. # MACs : OpenSSH 2.5.0 and later [3]
  711. # NoHostAuthenticationForLocalhost : OpenSSH 3.0.0 and later
  712. # NumberOfPasswordPrompts : OpenSSH 1.2.1 and later
  713. # PasswordAuthentication : OpenSSH 1.2.1 and later
  714. # PermitLocalCommand : OpenSSH 4.3.0 and later
  715. # Port : OpenSSH 1.2.1 and later
  716. # PreferredAuthentications : OpenSSH 2.5.2 and later
  717. # Protocol : OpenSSH 2.1.0 and later
  718. # ProxyCommand : OpenSSH 1.2.1 and later [3]
  719. # PubkeyAuthentication : OpenSSH 2.5.0 and later
  720. # RekeyLimit : OpenSSH 3.7.0 and later
  721. # RemoteForward : OpenSSH 1.2.1 and later [3]
  722. # RhostsRSAAuthentication : OpenSSH 1.2.1 and later
  723. # RSAAuthentication : OpenSSH 1.2.1 and later
  724. # SendEnv : OpenSSH 3.9.0 and later
  725. # ServerAliveCountMax : OpenSSH 3.8.0 and later
  726. # ServerAliveInterval : OpenSSH 3.8.0 and later
  727. # SmartcardDevice : OpenSSH 2.9.9 and later [1][3]
  728. # StrictHostKeyChecking : OpenSSH 1.2.1 and later
  729. # TCPKeepAlive : OpenSSH 3.8.0 and later
  730. # Tunnel : OpenSSH 4.3.0 and later
  731. # TunnelDevice : OpenSSH 4.3.0 and later [3]
  732. # UsePAM : OpenSSH 3.7.0 and later [1][2][3]
  733. # UsePrivilegedPort : OpenSSH 1.2.1 and later
  734. # User : OpenSSH 1.2.1 and later
  735. # UserKnownHostsFile : OpenSSH 1.2.1 and later
  736. # VerifyHostKeyDNS : OpenSSH 3.8.0 and later
  737. # XAuthLocation : OpenSSH 2.1.1 and later [3]
  738. #
  739. # [1] Option only available if activated at compile time
  740. # [2] Option specific for portable versions
  741. # [3] Option not used in our ssh client config file
  742. #***************************************************************************
  743. # Initialize ssh config with options actually supported in OpenSSH 2.9.9
  744. #
  745. logmsg 'generating ssh client config file...' if($verbose);
  746. @cfgarr = ();
  747. push @cfgarr, '# This is a generated file. Do not edit.';
  748. push @cfgarr, "# $sshverstr ssh client configuration file for curl testing";
  749. push @cfgarr, '#';
  750. push @cfgarr, 'Host *';
  751. push @cfgarr, '#';
  752. push @cfgarr, "Port $port";
  753. push @cfgarr, "HostName $listenaddr";
  754. push @cfgarr, "User $username";
  755. push @cfgarr, 'Protocol 2';
  756. push @cfgarr, '#';
  757. push @cfgarr, "BindAddress $listenaddr";
  758. push @cfgarr, "DynamicForward $socksport";
  759. push @cfgarr, '#';
  760. push @cfgarr, "IdentityFile $path/curl_client_key";
  761. push @cfgarr, "UserKnownHostsFile $path/$knownhosts";
  762. push @cfgarr, '#';
  763. push @cfgarr, 'BatchMode yes';
  764. push @cfgarr, 'ChallengeResponseAuthentication no';
  765. push @cfgarr, 'CheckHostIP no';
  766. push @cfgarr, 'ClearAllForwardings no';
  767. push @cfgarr, 'Compression no';
  768. push @cfgarr, 'ConnectionAttempts 3';
  769. push @cfgarr, 'ForwardAgent no';
  770. push @cfgarr, 'ForwardX11 no';
  771. push @cfgarr, 'GatewayPorts no';
  772. push @cfgarr, 'GlobalKnownHostsFile /dev/null';
  773. push @cfgarr, 'HostbasedAuthentication no';
  774. push @cfgarr, 'KbdInteractiveAuthentication no';
  775. push @cfgarr, "LogLevel $loglevel";
  776. push @cfgarr, 'NumberOfPasswordPrompts 0';
  777. push @cfgarr, 'PasswordAuthentication no';
  778. push @cfgarr, 'PreferredAuthentications publickey';
  779. push @cfgarr, 'PubkeyAuthentication yes';
  780. push @cfgarr, 'RhostsRSAAuthentication no';
  781. push @cfgarr, 'RSAAuthentication no';
  782. push @cfgarr, 'StrictHostKeyChecking yes';
  783. push @cfgarr, 'UsePrivilegedPort no';
  784. push @cfgarr, '#';
  785. #***************************************************************************
  786. # Options supported in ssh client newer than OpenSSH 2.9.9
  787. #
  788. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) {
  789. push @cfgarr, 'AddressFamily any';
  790. }
  791. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) ||
  792. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  793. push @cfgarr, 'ConnectTimeout 30';
  794. }
  795. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) {
  796. push @cfgarr, 'ControlMaster no';
  797. }
  798. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 420)) {
  799. push @cfgarr, 'ControlPath none';
  800. }
  801. if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) {
  802. push @cfgarr, 'DisableBanner yes';
  803. }
  804. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 360)) {
  805. push @cfgarr, 'EnableSSHKeysign no';
  806. }
  807. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 440)) {
  808. push @cfgarr, 'ExitOnForwardFailure yes';
  809. }
  810. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) ||
  811. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  812. push @cfgarr, 'ForwardX11Trusted no';
  813. }
  814. if(($sshd_builtwith_GSSAPI) && ($sshdid eq $sshid) &&
  815. ($sshdvernum == $sshvernum)) {
  816. push @cfgarr, 'GSSAPIAuthentication no';
  817. push @cfgarr, 'GSSAPIDelegateCredentials no';
  818. if($sshid =~ /SunSSH/) {
  819. push @cfgarr, 'GSSAPIKeyExchange no';
  820. }
  821. }
  822. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 400)) ||
  823. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  824. push @cfgarr, 'HashKnownHosts no';
  825. }
  826. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) {
  827. push @cfgarr, 'IdentitiesOnly yes';
  828. }
  829. if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) {
  830. push @cfgarr, 'IgnoreIfUnknown no';
  831. }
  832. if((($sshid =~ /OpenSSH/) && ($sshvernum < 380)) ||
  833. ($sshid =~ /SunSSH/)) {
  834. push @cfgarr, 'KeepAlive no';
  835. }
  836. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 300)) ||
  837. ($sshid =~ /SunSSH/)) {
  838. push @cfgarr, 'NoHostAuthenticationForLocalhost no';
  839. }
  840. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) {
  841. push @cfgarr, 'PermitLocalCommand no';
  842. }
  843. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) ||
  844. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  845. push @cfgarr, 'RekeyLimit 1G';
  846. }
  847. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) {
  848. push @cfgarr, 'SendEnv';
  849. }
  850. if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) ||
  851. (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
  852. push @cfgarr, 'ServerAliveCountMax 3';
  853. push @cfgarr, 'ServerAliveInterval 0';
  854. }
  855. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) {
  856. push @cfgarr, 'TCPKeepAlive no';
  857. }
  858. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) {
  859. push @cfgarr, 'Tunnel no';
  860. }
  861. if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) {
  862. push @cfgarr, 'VerifyHostKeyDNS no';
  863. }
  864. push @cfgarr, '#';
  865. #***************************************************************************
  866. # Write out resulting ssh client configuration file for curl's tests
  867. #
  868. $error = dump_array($sshconfig, @cfgarr);
  869. if($error) {
  870. logmsg $error;
  871. exit 1;
  872. }
  873. #***************************************************************************
  874. # Initialize client sftp config with options actually supported.
  875. #
  876. logmsg 'generating sftp client config file...' if($verbose);
  877. splice @cfgarr, 1, 1, "# $sshverstr sftp client configuration file for curl testing";
  878. #
  879. for(my $i = scalar(@cfgarr) - 1; $i > 0; $i--) {
  880. if($cfgarr[$i] =~ /^DynamicForward/) {
  881. splice @cfgarr, $i, 1;
  882. next;
  883. }
  884. if($cfgarr[$i] =~ /^ClearAllForwardings/) {
  885. splice @cfgarr, $i, 1, "ClearAllForwardings yes";
  886. next;
  887. }
  888. }
  889. #***************************************************************************
  890. # Write out resulting sftp client configuration file for curl's tests
  891. #
  892. $error = dump_array($sftpconfig, @cfgarr);
  893. if($error) {
  894. logmsg $error;
  895. exit 1;
  896. }
  897. @cfgarr = ();
  898. #***************************************************************************
  899. # Generate client sftp commands batch file for sftp server verification
  900. #
  901. logmsg 'generating sftp client commands file...' if($verbose);
  902. push @cfgarr, 'pwd';
  903. push @cfgarr, 'quit';
  904. $error = dump_array($sftpcmds, @cfgarr);
  905. if($error) {
  906. logmsg $error;
  907. exit 1;
  908. }
  909. @cfgarr = ();
  910. #***************************************************************************
  911. # Start the ssh server daemon without forking it
  912. #
  913. logmsg "SCP/SFTP server listening on port $port" if($verbose);
  914. my $rc = system "$sshd -e -D -f $sshdconfig > $sshdlog 2>&1";
  915. if($rc == -1) {
  916. logmsg "$sshd failed with: $!";
  917. }
  918. elsif($rc & 127) {
  919. logmsg sprintf("$sshd died with signal %d, and %s coredump",
  920. ($rc & 127), ($rc & 128)?'a':'no');
  921. }
  922. elsif($verbose && ($rc >> 8)) {
  923. logmsg sprintf("$sshd exited with %d", $rc >> 8);
  924. }
  925. #***************************************************************************
  926. # Clean up once the server has stopped
  927. #
  928. unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf, $knownhosts);
  929. unlink($sshdconfig, $sshconfig, $sftpconfig);
  930. exit 0;