1package ProFTPD::Tests::Modules::mod_sftp_sql;
2
3use lib qw(t/lib);
4use base qw(ProFTPD::TestSuite::Child);
5use strict;
6
7use Digest::MD5;
8use File::Copy;
9use File::Spec;
10use IO::Handle;
11use POSIX qw(:fcntl_h);
12
13use ProFTPD::TestSuite::Utils qw(:auth :config :features :running :test :testsuite);
14
15$| = 1;
16
17my $order = 0;
18
19my $TESTS = {
20  ssh2_auth_publickey_rsa_sql => {
21    order => ++$order,
22    test_class => [qw(forking ssh2)],
23  },
24
25  ssh2_auth_publickey_rsa_sql_var_U => {
26    order => ++$order,
27    test_class => [qw(forking ssh2)],
28  },
29
30  ssh2_auth_publickey_rsa_sql_var_u => {
31    order => ++$order,
32    test_class => [qw(forking ssh2)],
33  },
34
35  ssh2_auth_publickey_dsa_sql => {
36    order => ++$order,
37    test_class => [qw(forking ssh2)],
38  },
39
40  ssh2_auth_publickey_rsa_dsa_sql => {
41    order => ++$order,
42    test_class => [qw(forking ssh2)],
43  },
44
45  ssh2_auth_publickey_rsa_sql_rfc4716 => {
46    order => ++$order,
47    test_class => [qw(forking ssh2)],
48  },
49
50  ssh2_auth_publickey_rsa_sql_rfc4716_with_continued_line => {
51    order => ++$order,
52    test_class => [qw(forking ssh2)],
53  },
54
55  ssh2_auth_publickey_dsa_sql_rfc4716 => {
56    order => ++$order,
57    test_class => [qw(forking ssh2)],
58  },
59
60  ssh2_auth_publickey_rsa_dsa_sql_rfc4716 => {
61    order => ++$order,
62    test_class => [qw(forking ssh2)],
63  },
64
65  ssh2_auth_publickey_multiple_keys_one_row_bug3942 => {
66    order => ++$order,
67    test_class => [qw(bug forking ssh2)],
68  },
69
70  ssh2_auth_publickey_rsa_sql_fp_env_vars => {
71    order => ++$order,
72    test_class => [qw(forking ssh2)],
73  },
74
75  ssh2_auth_publickey_rsa_sql_rfc4716_overlong_comment_bug4155 => {
76    order => ++$order,
77    test_class => [qw(bug forking ssh2)],
78  },
79
80  ssh2_auth_publickey_rsa_sql_invalid_format_bug4350 => {
81    order => ++$order,
82    test_class => [qw(bug forking ssh2)],
83  },
84
85};
86
87sub new {
88  return shift()->SUPER::new(@_);
89}
90
91sub list_tests {
92  # Check for the required Perl modules:
93  #
94  #  Net-SSH2
95  #  Net-SSH2-SFTP
96
97  my $required = [qw(
98    Net::SSH2
99    Net::SSH2::SFTP
100  )];
101
102  foreach my $req (@$required) {
103    eval "use $req";
104    if ($@) {
105      print STDERR "\nWARNING:\n + Module '$req' not found, skipping all tests\n";
106
107      if ($ENV{TEST_VERBOSE}) {
108        print STDERR "Unable to load $req: $@\n";
109      }
110
111      return qw(testsuite_empty_test);
112    }
113  }
114
115#  return testsuite_get_runnable_tests($TESTS);
116  return qw(
117    ssh2_auth_publickey_rsa_sql_invalid_format_bug4350
118  );
119}
120
121sub set_up {
122  my $self = shift;
123  $self->SUPER::set_up(@_);
124
125  # Make sure that mod_sftp does not complain about permissions on the hostkey
126  # files.
127
128  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
129  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
130
131  unless (chmod(0400, $rsa_host_key, $dsa_host_key)) {
132    die("Can't set perms on $rsa_host_key, $dsa_host_key: $!");
133  }
134}
135
136sub ssh2_auth_publickey_rsa_sql {
137  my $self = shift;
138  my $tmpdir = $self->{tmpdir};
139
140  my $config_file = "$tmpdir/sftp.conf";
141  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
142  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
143
144  my $log_file = test_get_logfile();
145
146  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
147  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
148
149  my $user = 'proftpd';
150  my $passwd = 'test';
151  my $group = 'ftpd';
152  my $home_dir = File::Spec->rel2abs($tmpdir);
153  my $uid = 500;
154  my $gid = 500;
155
156  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
157
158  my $rsa_data = 'AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7jGx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00ydqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84uO6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMmef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPkByq2pv4VBo953gK7f1AQ==';
159
160  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
161
162  my $fh;
163  if (open($fh, "> $db_script")) {
164    print $fh <<EOS;
165CREATE TABLE sftpuserkeys (
166  name TEXT NOT NULL PRIMARY KEY,
167  key BLOB NOT NULL
168);
169
170INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_data');
171
172CREATE TABLE users (
173  userid TEXT NOT NULL PRIMARY KEY,
174  passwd TEXT,
175  uid INTEGER,
176  gid INTEGER,
177  homedir TEXT,
178  shell TEXT
179);
180
181EOS
182    unless (close($fh)) {
183      die("Can't write $db_script: $!");
184    }
185
186  } else {
187    die("Can't open $db_script: $!");
188  }
189
190  my $cmd = "sqlite3 $db_file < $db_script";
191  if ($ENV{TEST_VERBOSE}) {
192    print STDERR "Executing sqlite3: $cmd\n";
193  }
194
195  my @output = `$cmd`;
196
197  unlink($db_script);
198
199  # Make sure that, if we're running as root, that the home directory has
200  # permissions/privs set for the account we create
201  if ($< == 0) {
202    unless (chmod(0755, $home_dir)) {
203      die("Can't set perms on $home_dir to 0755: $!");
204    }
205
206    unless (chown($uid, $gid, $home_dir)) {
207      die("Can't set owner of $home_dir to $uid/$gid: $!");
208    }
209  }
210
211  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
212    '/bin/bash');
213  auth_group_write($auth_group_file, $group, $gid, $user);
214
215  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
216  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
217
218  my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key');
219  my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub');
220
221  my $config = {
222    PidFile => $pid_file,
223    ScoreboardFile => $scoreboard_file,
224    SystemLog => $log_file,
225    TraceLog => $log_file,
226    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
227
228    AuthUserFile => $auth_user_file,
229    AuthGroupFile => $auth_group_file,
230
231    IfModules => {
232      'mod_delay.c' => {
233        DelayEngine => 'off',
234      },
235
236      'mod_sql_sqlite.c' => {
237        SQLAuthenticate => 'users usersetfast',
238        SQLConnectInfo => $db_file,
239        SQLLogFile => $log_file,
240        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
241      },
242
243      'mod_sftp.c' => [
244        "SFTPEngine on",
245        "SFTPLog $log_file",
246        "SFTPHostKey $rsa_host_key",
247        "SFTPHostKey $dsa_host_key",
248        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
249      ],
250    },
251  };
252
253  my ($port, $config_user, $config_group) = config_write($config_file, $config);
254
255  # Open pipes, for use between the parent and child processes.  Specifically,
256  # the child will indicate when it's done with its test by writing a message
257  # to the parent.
258  my ($rfh, $wfh);
259  unless (pipe($rfh, $wfh)) {
260    die("Can't open pipe: $!");
261  }
262
263  require Net::SSH2;
264
265  my $ex;
266
267  # Fork child
268  $self->handle_sigchld();
269  defined(my $pid = fork()) or die("Can't fork: $!");
270  if ($pid) {
271    eval {
272      my $ssh2 = Net::SSH2->new();
273
274      sleep(1);
275
276      unless ($ssh2->connect('127.0.0.1', $port)) {
277        my ($err_code, $err_name, $err_str) = $ssh2->error();
278        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
279      }
280
281      unless ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) {
282        my ($err_code, $err_name, $err_str) = $ssh2->error();
283        die("RSA publickey authentication failed: [$err_name] ($err_code) $err_str");
284      }
285
286      $ssh2->disconnect();
287    };
288
289    if ($@) {
290      $ex = $@;
291    }
292
293    $wfh->print("done\n");
294    $wfh->flush();
295
296  } else {
297    eval { server_wait($config_file, $rfh) };
298    if ($@) {
299      warn($@);
300      exit 1;
301    }
302
303    exit 0;
304  }
305
306  # Stop server
307  server_stop($pid_file);
308
309  $self->assert_child_ok($pid);
310
311  if ($ex) {
312    test_append_logfile($log_file, $ex);
313    unlink($log_file);
314
315    die($ex);
316  }
317
318  unlink($log_file, $db_file);
319}
320
321sub ssh2_auth_publickey_rsa_sql_var_U {
322  my $self = shift;
323  my $tmpdir = $self->{tmpdir};
324
325  my $config_file = "$tmpdir/sftp.conf";
326  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
327  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
328
329  my $log_file = test_get_logfile();
330
331  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
332  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
333
334  my $user = 'proftpd';
335  my $passwd = 'test';
336  my $group = 'ftpd';
337  my $home_dir = File::Spec->rel2abs($tmpdir);
338  my $uid = 500;
339  my $gid = 500;
340
341  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
342
343  my $rsa_data = 'AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7jGx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00ydqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84uO6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMmef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPkByq2pv4VBo953gK7f1AQ==';
344
345  # Make sure that, if we're running as root, that the home directory has
346  # permissions/privs set for the account we create
347  if ($< == 0) {
348    unless (chmod(0755, $home_dir)) {
349      die("Can't set perms on $home_dir to 0755: $!");
350    }
351
352    unless (chown($uid, $gid, $home_dir)) {
353      die("Can't set owner of $home_dir to $uid/$gid: $!");
354    }
355  }
356
357  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
358    '/bin/bash');
359  auth_group_write($auth_group_file, $group, $gid, $user);
360
361  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
362  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
363
364  my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key');
365  my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub');
366
367  my $config = {
368    PidFile => $pid_file,
369    ScoreboardFile => $scoreboard_file,
370    SystemLog => $log_file,
371    TraceLog => $log_file,
372    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
373
374    AuthUserFile => $auth_user_file,
375    AuthGroupFile => $auth_group_file,
376
377    IfModules => {
378      'mod_delay.c' => {
379        DelayEngine => 'off',
380      },
381
382      'mod_sql_sqlite.c' => {
383        SQLAuthenticate => 'users usersetfast',
384        SQLConnectInfo => $db_file,
385        SQLLogFile => $log_file,
386        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%U\'"',
387      },
388
389      'mod_sftp.c' => [
390        "SFTPEngine on",
391        "SFTPLog $log_file",
392        "SFTPHostKey $rsa_host_key",
393        "SFTPHostKey $dsa_host_key",
394        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
395      ],
396    },
397  };
398
399  my ($port, $config_user, $config_group) = config_write($config_file, $config);
400
401  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
402
403  my $fh;
404  if (open($fh, "> $db_script")) {
405    print $fh <<EOS;
406CREATE TABLE sftpuserkeys (
407  name TEXT NOT NULL PRIMARY KEY,
408  key BLOB NOT NULL
409);
410
411INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_data');
412INSERT INTO sftpuserkeys (name, key) VALUES ('$config_user', '$rsa_data');
413
414CREATE TABLE users (
415  userid TEXT NOT NULL PRIMARY KEY,
416  passwd TEXT,
417  uid INTEGER,
418  gid INTEGER,
419  homedir TEXT,
420  shell TEXT
421);
422
423EOS
424    unless (close($fh)) {
425      die("Can't write $db_script: $!");
426    }
427
428  } else {
429    die("Can't open $db_script: $!");
430  }
431
432  my $cmd = "sqlite3 $db_file < $db_script";
433  if ($ENV{TEST_VERBOSE}) {
434    print STDERR "Executing sqlite3: $cmd\n";
435  }
436
437  my @output = `$cmd`;
438  if (scalar(@output) &&
439      $ENV{TEST_VERBOSE}) {
440    print STDERR "Output: ", join('', @output), "\n";
441  }
442
443  unlink($db_script);
444
445  # Open pipes, for use between the parent and child processes.  Specifically,
446  # the child will indicate when it's done with its test by writing a message
447  # to the parent.
448  my ($rfh, $wfh);
449  unless (pipe($rfh, $wfh)) {
450    die("Can't open pipe: $!");
451  }
452
453  require Net::SSH2;
454
455  my $ex;
456
457  # Fork child
458  $self->handle_sigchld();
459  defined(my $pid = fork()) or die("Can't fork: $!");
460  if ($pid) {
461    eval {
462      my $ssh2 = Net::SSH2->new();
463
464      sleep(1);
465
466      unless ($ssh2->connect('127.0.0.1', $port)) {
467        my ($err_code, $err_name, $err_str) = $ssh2->error();
468        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
469      }
470
471      unless ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) {
472        my ($err_code, $err_name, $err_str) = $ssh2->error();
473        die("RSA publickey authentication failed: [$err_name] ($err_code) $err_str");
474      }
475
476      $ssh2->disconnect();
477    };
478
479    if ($@) {
480      $ex = $@;
481    }
482
483    $wfh->print("done\n");
484    $wfh->flush();
485
486  } else {
487    eval { server_wait($config_file, $rfh) };
488    if ($@) {
489      warn($@);
490      exit 1;
491    }
492
493    exit 0;
494  }
495
496  # Stop server
497  server_stop($pid_file);
498
499  $self->assert_child_ok($pid);
500
501  if ($ex) {
502    test_append_logfile($log_file, $ex);
503    unlink($log_file);
504
505    die($ex);
506  }
507
508  unlink($log_file, $db_file);
509}
510
511sub ssh2_auth_publickey_rsa_sql_var_u {
512  my $self = shift;
513  my $tmpdir = $self->{tmpdir};
514
515  my $config_file = "$tmpdir/sftp.conf";
516  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
517  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
518
519  my $log_file = test_get_logfile();
520
521  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
522  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
523
524  my $user = 'proftpd';
525  my $passwd = 'test';
526  my $group = 'ftpd';
527  my $home_dir = File::Spec->rel2abs($tmpdir);
528  my $uid = 500;
529  my $gid = 500;
530
531  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
532
533  my $rsa_data = 'AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7jGx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00ydqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84uO6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMmef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPkByq2pv4VBo953gK7f1AQ==';
534
535  # Make sure that, if we're running as root, that the home directory has
536  # permissions/privs set for the account we create
537  if ($< == 0) {
538    unless (chmod(0755, $home_dir)) {
539      die("Can't set perms on $home_dir to 0755: $!");
540    }
541
542    unless (chown($uid, $gid, $home_dir)) {
543      die("Can't set owner of $home_dir to $uid/$gid: $!");
544    }
545  }
546
547  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
548    '/bin/bash');
549  auth_group_write($auth_group_file, $group, $gid, $user);
550
551  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
552  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
553
554  my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key');  my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub');
555
556  my $config = {
557    PidFile => $pid_file,
558    ScoreboardFile => $scoreboard_file,
559    SystemLog => $log_file,
560    TraceLog => $log_file,
561    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
562
563    AuthUserFile => $auth_user_file,
564    AuthGroupFile => $auth_group_file,
565
566    IfModules => {
567      'mod_delay.c' => {
568        DelayEngine => 'off',
569      },
570
571      'mod_sql_sqlite.c' => {
572        SQLAuthenticate => 'off',
573        SQLConnectInfo => $db_file,
574        SQLLogFile => $log_file,
575        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%u\'"',
576      },
577
578      'mod_sftp.c' => [
579        "SFTPEngine on",
580        "SFTPLog $log_file",
581        "SFTPHostKey $rsa_host_key",
582        "SFTPHostKey $dsa_host_key",
583        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
584      ],
585    },
586  };
587
588  my ($port, $config_user, $config_group) = config_write($config_file, $config);
589
590  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
591
592  my $fh;
593  if (open($fh, "> $db_script")) {
594    print $fh <<EOS;
595CREATE TABLE sftpuserkeys (
596  name TEXT NOT NULL PRIMARY KEY,
597  key BLOB NOT NULL
598);
599
600INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_data');
601INSERT INTO sftpuserkeys (name, key) VALUES ('$config_user', '$rsa_data');
602EOS
603    unless (close($fh)) {
604      die("Can't write $db_script: $!");
605    }
606
607  } else {
608    die("Can't open $db_script: $!");
609  }
610
611  my $cmd = "sqlite3 $db_file < $db_script";
612  if ($ENV{TEST_VERBOSE}) {
613    print STDERR "Executing sqlite3: $cmd\n";
614  }
615
616  my @output = `$cmd`;
617  if (scalar(@output) &&
618      $ENV{TEST_VERBOSE}) {
619    print STDERR "Output: ", join('', @output), "\n";
620  }
621
622  unlink($db_script);
623
624  # Open pipes, for use between the parent and child processes.  Specifically,
625  # the child will indicate when it's done with its test by writing a message
626  # to the parent.
627  my ($rfh, $wfh);
628  unless (pipe($rfh, $wfh)) {
629    die("Can't open pipe: $!");
630  }
631
632  require Net::SSH2;
633
634  my $ex;
635
636  # Fork child
637  $self->handle_sigchld();
638  defined(my $pid = fork()) or die("Can't fork: $!");
639  if ($pid) {
640    eval {
641      my $ssh2 = Net::SSH2->new();
642
643      sleep(1);
644
645      unless ($ssh2->connect('127.0.0.1', $port)) {
646        my ($err_code, $err_name, $err_str) = $ssh2->error();
647        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
648      }
649
650      # This should fail, since %u will resolve to '-' (the user has not
651      # been authenticated yet).
652      if ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) {
653        die("RSA publickey authentication succeeded unexpectly");
654      }
655
656      my ($err_code, $err_name, $err_str) = $ssh2->error();
657      my $expected = 'LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED';
658      $self->assert($expected eq $err_name,
659        test_msg("Expected error name '$expected', got '$err_name'"));
660
661      $ssh2->disconnect();
662    };
663
664    if ($@) {
665      $ex = $@;
666    }
667
668    $wfh->print("done\n");
669    $wfh->flush();
670
671  } else {
672    eval { server_wait($config_file, $rfh) };
673    if ($@) {
674      warn($@);
675      exit 1;
676    }
677
678    exit 0;
679  }
680
681  # Stop server
682  server_stop($pid_file);
683
684  $self->assert_child_ok($pid);
685
686  if ($ex) {
687    test_append_logfile($log_file, $ex);
688    unlink($log_file);
689
690    die($ex);
691  }
692
693  unlink($log_file, $db_file);
694}
695
696sub ssh2_auth_publickey_dsa_sql {
697  my $self = shift;
698  my $tmpdir = $self->{tmpdir};
699
700  my $config_file = "$tmpdir/sftp.conf";
701  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
702  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
703
704  my $log_file = test_get_logfile();
705
706  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
707  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
708
709  my $user = 'proftpd';
710  my $passwd = 'test';
711  my $group = 'ftpd';
712  my $home_dir = File::Spec->rel2abs($tmpdir);
713  my $uid = 500;
714  my $gid = 500;
715
716  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
717
718  my $dsa_data = 'AAAAB3NzaC1kc3MAAACBAJWsBFKoQ1HdluDnVacaPm+PDPuXAMxwpplFYafjDCye5Y2FZEjSA8GlLAsEk3XCw6JK2+ciE0I/XXn3+3cAkrdjDKQDRn8IcAANatgLSSjxS9XN4oNzKtrjSs3hOhv5ADhwKMcIhwSSf0cVRH9sGjQF3IiJBVnQjz6i//v+97otAAAAFQDqbZr3aGXlY0Q3UYS3XRNV8ZdWLwAAAIBVZ00AvPF6Kh9GUvXdUAEtNfe1JIThzC4rSc2Fyz3/mQA+GLUHtEq1ZLpO5D4PCjxHcR7N1tIarqR1f0GGjDGvaPocPNtMpaVxCsLWTCnua5fhIgZ3H24mSzd/j2TSDqIeV0DWWiWsFOTF+UzbxSDAinfDjLGV0XQ1jRhgoHS3hAAAAIAfONFEnSPWVLEl0Hv9yAozdWBmkyDijkk0zWWGh17z/Ef4ZRo5bwjsOQCx3c3XswdjDacoqUjep8EMs8MI4LpOx8SybGOGu8xyW3ceT+rdP1/S62JxBeL7SaIwCH0O9sPqeh44l8OHIKVh6lmyUr1KQFOnNJ/pRF0JutY1UDEUMQ==';
719
720  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
721
722  my $fh;
723  if (open($fh, "> $db_script")) {
724    print $fh <<EOS;
725CREATE TABLE sftpuserkeys (
726  name TEXT NOT NULL PRIMARY KEY,
727  key BLOB NOT NULL
728);
729
730INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$dsa_data');
731EOS
732    unless (close($fh)) {
733      die("Can't write $db_script: $!");
734    }
735
736  } else {
737    die("Can't open $db_script: $!");
738  }
739
740  my $cmd = "sqlite3 $db_file < $db_script";
741  if ($ENV{TEST_VERBOSE}) {
742    print STDERR "Executing sqlite3: $cmd\n";
743  }
744
745  my @output = `$cmd`;
746
747  unlink($db_script);
748
749  # Make sure that, if we're running as root, that the home directory has
750  # permissions/privs set for the account we create
751  if ($< == 0) {
752    unless (chmod(0755, $home_dir)) {
753      die("Can't set perms on $home_dir to 0755: $!");
754    }
755
756    unless (chown($uid, $gid, $home_dir)) {
757      die("Can't set owner of $home_dir to $uid/$gid: $!");
758    }
759  }
760
761  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
762    '/bin/bash');
763  auth_group_write($auth_group_file, $group, $gid, $user);
764
765  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
766  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
767
768  my $dsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_dsa_key');
769  my $dsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_dsa_key.pub');
770
771  my $config = {
772    PidFile => $pid_file,
773    ScoreboardFile => $scoreboard_file,
774    SystemLog => $log_file,
775    TraceLog => $log_file,
776    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
777
778    AuthUserFile => $auth_user_file,
779    AuthGroupFile => $auth_group_file,
780
781    IfModules => {
782      'mod_delay.c' => {
783        DelayEngine => 'off',
784      },
785
786      'mod_sql_sqlite.c' => {
787        SQLAuthenticate => 'off',
788        SQLConnectInfo => $db_file,
789        SQLLogFile => $log_file,
790        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
791      },
792
793      'mod_sftp.c' => [
794        "SFTPEngine on",
795        "SFTPLog $log_file",
796        "SFTPHostKey $rsa_host_key",
797        "SFTPHostKey $dsa_host_key",
798        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
799      ],
800    },
801  };
802
803  my ($port, $config_user, $config_group) = config_write($config_file, $config);
804
805  # Open pipes, for use between the parent and child processes.  Specifically,
806  # the child will indicate when it's done with its test by writing a message
807  # to the parent.
808  my ($rfh, $wfh);
809  unless (pipe($rfh, $wfh)) {
810    die("Can't open pipe: $!");
811  }
812
813  require Net::SSH2;
814
815  my $ex;
816
817  # Fork child
818  $self->handle_sigchld();
819  defined(my $pid = fork()) or die("Can't fork: $!");
820  if ($pid) {
821    eval {
822      my $ssh2 = Net::SSH2->new();
823
824      sleep(1);
825
826      unless ($ssh2->connect('127.0.0.1', $port)) {
827        my ($err_code, $err_name, $err_str) = $ssh2->error();
828        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
829      }
830
831      unless ($ssh2->auth_publickey($user, $dsa_pub_key, $dsa_priv_key)) {
832        my ($err_code, $err_name, $err_str) = $ssh2->error();
833        die("DSA publickey authentication failed: [$err_name] ($err_code) $err_str");
834      }
835
836      $ssh2->disconnect();
837    };
838
839    if ($@) {
840      $ex = $@;
841    }
842
843    $wfh->print("done\n");
844    $wfh->flush();
845
846  } else {
847    eval { server_wait($config_file, $rfh) };
848    if ($@) {
849      warn($@);
850      exit 1;
851    }
852
853    exit 0;
854  }
855
856  # Stop server
857  server_stop($pid_file);
858
859  $self->assert_child_ok($pid);
860
861  if ($ex) {
862    test_append_logfile($log_file, $ex);
863    unlink($log_file);
864
865    die($ex);
866  }
867
868  unlink($log_file, $db_file);
869}
870
871sub ssh2_auth_publickey_rsa_dsa_sql {
872  my $self = shift;
873  my $tmpdir = $self->{tmpdir};
874
875  my $config_file = "$tmpdir/sftp.conf";
876  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
877  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
878
879  my $log_file = test_get_logfile();
880
881  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
882  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
883
884  my $user = 'proftpd';
885  my $passwd = 'test';
886  my $group = 'ftpd';
887  my $home_dir = File::Spec->rel2abs($tmpdir);
888  my $uid = 500;
889  my $gid = 500;
890
891  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
892
893  my $rsa_data = 'AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7jGx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00ydqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84uO6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMmef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPkByq2pv4VBo953gK7f1AQ==';
894  my $dsa_data = 'AAAAB3NzaC1kc3MAAACBAJWsBFKoQ1HdluDnVacaPm+PDPuXAMxwpplFYafjDCye5Y2FZEjSA8GlLAsEk3XCw6JK2+ciE0I/XXn3+3cAkrdjDKQDRn8IcAANatgLSSjxS9XN4oNzKtrjSs3hOhv5ADhwKMcIhwSSf0cVRH9sGjQF3IiJBVnQjz6i//v+97otAAAAFQDqbZr3aGXlY0Q3UYS3XRNV8ZdWLwAAAIBVZ00AvPF6Kh9GUvXdUAEtNfe1JIThzC4rSc2Fyz3/mQA+GLUHtEq1ZLpO5D4PCjxHcR7N1tIarqR1f0GGjDGvaPocPNtMpaVxCsLWTCnua5fhIgZ3H24mSzd/j2TSDqIeV0DWWiWsFOTF+UzbxSDAinfDjLGV0XQ1jRhgoHS3hAAAAIAfONFEnSPWVLEl0Hv9yAozdWBmkyDijkk0zWWGh17z/Ef4ZRo5bwjsOQCx3c3XswdjDacoqUjep8EMs8MI4LpOx8SybGOGu8xyW3ceT+rdP1/S62JxBeL7SaIwCH0O9sPqeh44l8OHIKVh6lmyUr1KQFOnNJ/pRF0JutY1UDEUMQ==';
895
896  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
897
898  my $fh;
899  if (open($fh, "> $db_script")) {
900    print $fh <<EOS;
901CREATE TABLE sftpuserkeys (
902  name TEXT NOT NULL,
903  key BLOB NOT NULL
904);
905
906INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_data');
907INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$dsa_data');
908EOS
909    unless (close($fh)) {
910      die("Can't write $db_script: $!");
911    }
912
913  } else {
914    die("Can't open $db_script: $!");
915  }
916
917  my $cmd = "sqlite3 $db_file < $db_script";
918  if ($ENV{TEST_VERBOSE}) {
919    print STDERR "Executing sqlite3: $cmd\n";
920  }
921
922  my @output = `$cmd`;
923
924  unlink($db_script);
925
926  # Make sure that, if we're running as root, that the home directory has
927  # permissions/privs set for the account we create
928  if ($< == 0) {
929    unless (chmod(0755, $home_dir)) {
930      die("Can't set perms on $home_dir to 0755: $!");
931    }
932
933    unless (chown($uid, $gid, $home_dir)) {
934      die("Can't set owner of $home_dir to $uid/$gid: $!");
935    }
936  }
937
938  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
939    '/bin/bash');
940  auth_group_write($auth_group_file, $group, $gid, $user);
941
942  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
943  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
944
945  my $dsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_dsa_key');
946  my $dsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_dsa_key.pub');
947
948  my $config = {
949    PidFile => $pid_file,
950    ScoreboardFile => $scoreboard_file,
951    SystemLog => $log_file,
952    TraceLog => $log_file,
953    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
954
955    AuthUserFile => $auth_user_file,
956    AuthGroupFile => $auth_group_file,
957
958    IfModules => {
959      'mod_delay.c' => {
960        DelayEngine => 'off',
961      },
962
963      'mod_sql_sqlite.c' => {
964        SQLAuthenticate => 'off',
965        SQLConnectInfo => $db_file,
966        SQLLogFile => $log_file,
967        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
968      },
969
970      'mod_sftp.c' => [
971        "SFTPEngine on",
972        "SFTPLog $log_file",
973        "SFTPHostKey $rsa_host_key",
974        "SFTPHostKey $dsa_host_key",
975        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
976      ],
977    },
978  };
979
980  my ($port, $config_user, $config_group) = config_write($config_file, $config);
981
982  # Open pipes, for use between the parent and child processes.  Specifically,
983  # the child will indicate when it's done with its test by writing a message
984  # to the parent.
985  my ($rfh, $wfh);
986  unless (pipe($rfh, $wfh)) {
987    die("Can't open pipe: $!");
988  }
989
990  require Net::SSH2;
991
992  my $ex;
993
994  # Fork child
995  $self->handle_sigchld();
996  defined(my $pid = fork()) or die("Can't fork: $!");
997  if ($pid) {
998    eval {
999      my $ssh2 = Net::SSH2->new();
1000
1001      sleep(1);
1002
1003      unless ($ssh2->connect('127.0.0.1', $port)) {
1004        my ($err_code, $err_name, $err_str) = $ssh2->error();
1005        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
1006      }
1007
1008      unless ($ssh2->auth_publickey($user, $dsa_pub_key, $dsa_priv_key)) {
1009        my ($err_code, $err_name, $err_str) = $ssh2->error();
1010        die("DSA publickey authentication failed: [$err_name] ($err_code) $err_str");
1011      }
1012
1013      $ssh2->disconnect();
1014    };
1015
1016    if ($@) {
1017      $ex = $@;
1018    }
1019
1020    $wfh->print("done\n");
1021    $wfh->flush();
1022
1023  } else {
1024    eval { server_wait($config_file, $rfh) };
1025    if ($@) {
1026      warn($@);
1027      exit 1;
1028    }
1029
1030    exit 0;
1031  }
1032
1033  # Stop server
1034  server_stop($pid_file);
1035
1036  $self->assert_child_ok($pid);
1037
1038  if ($ex) {
1039    test_append_logfile($log_file, $ex);
1040    unlink($log_file);
1041
1042    die($ex);
1043  }
1044
1045  unlink($log_file, $db_file);
1046}
1047
1048sub ssh2_auth_publickey_rsa_sql_rfc4716 {
1049  my $self = shift;
1050  my $tmpdir = $self->{tmpdir};
1051
1052  my $config_file = "$tmpdir/sftp.conf";
1053  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
1054  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
1055
1056  my $log_file = test_get_logfile();
1057
1058  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
1059  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
1060
1061  my $user = 'proftpd';
1062  my $passwd = 'test';
1063  my $group = 'ftpd';
1064  my $home_dir = File::Spec->rel2abs($tmpdir);
1065  my $uid = 500;
1066  my $gid = 500;
1067
1068  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
1069
1070  my $rsa_rfc4716_data = '---- BEGIN SSH2 PUBLIC KEY ----
1071Comment: "2048-bit RSA, converted from OpenSSH by tj@familiar"
1072AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7j
1073Gx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00y
1074dqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84u
1075O6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMm
1076ef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPk
1077Byq2pv4VBo953gK7f1AQ==
1078---- END SSH2 PUBLIC KEY ----';
1079
1080  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
1081
1082  my $fh;
1083  if (open($fh, "> $db_script")) {
1084    print $fh <<EOS;
1085CREATE TABLE sftpuserkeys (
1086  name TEXT NOT NULL PRIMARY KEY,
1087  key BLOB NOT NULL
1088);
1089
1090INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_rfc4716_data');
1091EOS
1092    unless (close($fh)) {
1093      die("Can't write $db_script: $!");
1094    }
1095
1096  } else {
1097    die("Can't open $db_script: $!");
1098  }
1099
1100  my $cmd = "sqlite3 $db_file < $db_script";
1101  if ($ENV{TEST_VERBOSE}) {
1102    print STDERR "Executing sqlite3: $cmd\n";
1103  }
1104
1105  my @output = `$cmd`;
1106
1107  unlink($db_script);
1108
1109  # Make sure that, if we're running as root, that the home directory has
1110  # permissions/privs set for the account we create
1111  if ($< == 0) {
1112    unless (chmod(0755, $home_dir)) {
1113      die("Can't set perms on $home_dir to 0755: $!");
1114    }
1115
1116    unless (chown($uid, $gid, $home_dir)) {
1117      die("Can't set owner of $home_dir to $uid/$gid: $!");
1118    }
1119  }
1120
1121  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
1122    '/bin/bash');
1123  auth_group_write($auth_group_file, $group, $gid, $user);
1124
1125  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
1126  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
1127
1128  my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key');
1129  my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub');
1130
1131  my $config = {
1132    PidFile => $pid_file,
1133    ScoreboardFile => $scoreboard_file,
1134    SystemLog => $log_file,
1135    TraceLog => $log_file,
1136    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
1137
1138    AuthUserFile => $auth_user_file,
1139    AuthGroupFile => $auth_group_file,
1140
1141    IfModules => {
1142      'mod_delay.c' => {
1143        DelayEngine => 'off',
1144      },
1145
1146      'mod_sql_sqlite.c' => {
1147        SQLAuthenticate => 'off',
1148        SQLConnectInfo => $db_file,
1149        SQLLogFile => $log_file,
1150        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
1151      },
1152
1153      'mod_sftp.c' => [
1154        "SFTPEngine on",
1155        "SFTPLog $log_file",
1156        "SFTPHostKey $rsa_host_key",
1157        "SFTPHostKey $dsa_host_key",
1158        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
1159      ],
1160    },
1161  };
1162
1163  my ($port, $config_user, $config_group) = config_write($config_file, $config);
1164
1165  # Open pipes, for use between the parent and child processes.  Specifically,
1166  # the child will indicate when it's done with its test by writing a message
1167  # to the parent.
1168  my ($rfh, $wfh);
1169  unless (pipe($rfh, $wfh)) {
1170    die("Can't open pipe: $!");
1171  }
1172
1173  require Net::SSH2;
1174
1175  my $ex;
1176
1177  # Fork child
1178  $self->handle_sigchld();
1179  defined(my $pid = fork()) or die("Can't fork: $!");
1180  if ($pid) {
1181    eval {
1182      my $ssh2 = Net::SSH2->new();
1183
1184      sleep(1);
1185
1186      unless ($ssh2->connect('127.0.0.1', $port)) {
1187        my ($err_code, $err_name, $err_str) = $ssh2->error();
1188        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
1189      }
1190
1191      unless ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) {
1192        my ($err_code, $err_name, $err_str) = $ssh2->error();
1193        die("RSA publickey authentication failed: [$err_name] ($err_code) $err_str");
1194      }
1195
1196      $ssh2->disconnect();
1197    };
1198
1199    if ($@) {
1200      $ex = $@;
1201    }
1202
1203    $wfh->print("done\n");
1204    $wfh->flush();
1205
1206  } else {
1207    eval { server_wait($config_file, $rfh) };
1208    if ($@) {
1209      warn($@);
1210      exit 1;
1211    }
1212
1213    exit 0;
1214  }
1215
1216  # Stop server
1217  server_stop($pid_file);
1218
1219  $self->assert_child_ok($pid);
1220
1221  if ($ex) {
1222    test_append_logfile($log_file, $ex);
1223    unlink($log_file);
1224
1225    die($ex);
1226  }
1227
1228  unlink($log_file, $db_file);
1229}
1230
1231sub ssh2_auth_publickey_rsa_sql_rfc4716_with_continued_line {
1232  my $self = shift;
1233  my $tmpdir = $self->{tmpdir};
1234
1235  my $config_file = "$tmpdir/sftp.conf";
1236  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
1237  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
1238
1239  my $log_file = test_get_logfile();
1240
1241  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
1242  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
1243
1244  my $user = 'proftpd';
1245  my $passwd = 'test';
1246  my $group = 'ftpd';
1247  my $home_dir = File::Spec->rel2abs($tmpdir);
1248  my $uid = 500;
1249  my $gid = 500;
1250
1251  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
1252
1253  my $rsa_rfc4716_data = '---- BEGIN SSH2 PUBLIC KEY ----
1254Subject: at93590
1255Comment: "2048-bit dsa, at93590@isgswapd4n2, Tue Jun 22 2010 15:00:34 \
1256-0400"
1257AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7j
1258Gx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00y
1259dqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84u
1260O6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMm
1261ef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPk
1262Byq2pv4VBo953gK7f1AQ==
1263---- END SSH2 PUBLIC KEY ----';
1264
1265  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
1266
1267  my $fh;
1268  if (open($fh, "> $db_script")) {
1269    print $fh <<EOS;
1270CREATE TABLE sftpuserkeys (
1271  name TEXT NOT NULL PRIMARY KEY,
1272  key BLOB NOT NULL
1273);
1274
1275INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_rfc4716_data');
1276EOS
1277    unless (close($fh)) {
1278      die("Can't write $db_script: $!");
1279    }
1280
1281  } else {
1282    die("Can't open $db_script: $!");
1283  }
1284
1285  my $cmd = "sqlite3 $db_file < $db_script";
1286  if ($ENV{TEST_VERBOSE}) {
1287    print STDERR "Executing sqlite3: $cmd\n";
1288  }
1289
1290  my @output = `$cmd`;
1291
1292  unlink($db_script);
1293
1294  # Make sure that, if we're running as root, that the home directory has
1295  # permissions/privs set for the account we create
1296  if ($< == 0) {
1297    unless (chmod(0755, $home_dir)) {
1298      die("Can't set perms on $home_dir to 0755: $!");
1299    }
1300
1301    unless (chown($uid, $gid, $home_dir)) {
1302      die("Can't set owner of $home_dir to $uid/$gid: $!");
1303    }
1304  }
1305
1306  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
1307    '/bin/bash');
1308  auth_group_write($auth_group_file, $group, $gid, $user);
1309
1310  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
1311  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
1312
1313  my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key');
1314  my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub');
1315
1316  my $config = {
1317    PidFile => $pid_file,
1318    ScoreboardFile => $scoreboard_file,
1319    SystemLog => $log_file,
1320    TraceLog => $log_file,
1321    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
1322
1323    AuthUserFile => $auth_user_file,
1324    AuthGroupFile => $auth_group_file,
1325
1326    IfModules => {
1327      'mod_delay.c' => {
1328        DelayEngine => 'off',
1329      },
1330
1331      'mod_sql_sqlite.c' => {
1332        SQLAuthenticate => 'off',
1333        SQLConnectInfo => $db_file,
1334        SQLLogFile => $log_file,
1335        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
1336      },
1337
1338      'mod_sftp.c' => [
1339        "SFTPEngine on",
1340        "SFTPLog $log_file",
1341        "SFTPHostKey $rsa_host_key",
1342        "SFTPHostKey $dsa_host_key",
1343        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
1344      ],
1345    },
1346  };
1347
1348  my ($port, $config_user, $config_group) = config_write($config_file, $config);
1349
1350  # Open pipes, for use between the parent and child processes.  Specifically,
1351  # the child will indicate when it's done with its test by writing a message
1352  # to the parent.
1353  my ($rfh, $wfh);
1354  unless (pipe($rfh, $wfh)) {
1355    die("Can't open pipe: $!");
1356  }
1357
1358  require Net::SSH2;
1359
1360  my $ex;
1361
1362  # Fork child
1363  $self->handle_sigchld();
1364  defined(my $pid = fork()) or die("Can't fork: $!");
1365  if ($pid) {
1366    eval {
1367      my $ssh2 = Net::SSH2->new();
1368
1369      sleep(1);
1370
1371      unless ($ssh2->connect('127.0.0.1', $port)) {
1372        my ($err_code, $err_name, $err_str) = $ssh2->error();
1373        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
1374      }
1375
1376      unless ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) {
1377        my ($err_code, $err_name, $err_str) = $ssh2->error();
1378        die("RSA publickey authentication failed: [$err_name] ($err_code) $err_str");
1379      }
1380
1381      $ssh2->disconnect();
1382    };
1383
1384    if ($@) {
1385      $ex = $@;
1386    }
1387
1388    $wfh->print("done\n");
1389    $wfh->flush();
1390
1391  } else {
1392    eval { server_wait($config_file, $rfh) };
1393    if ($@) {
1394      warn($@);
1395      exit 1;
1396    }
1397
1398    exit 0;
1399  }
1400
1401  # Stop server
1402  server_stop($pid_file);
1403
1404  $self->assert_child_ok($pid);
1405
1406  if ($ex) {
1407    test_append_logfile($log_file, $ex);
1408    unlink($log_file);
1409
1410    die($ex);
1411  }
1412
1413  unlink($log_file, $db_file);
1414}
1415
1416sub ssh2_auth_publickey_dsa_sql_rfc4716 {
1417  my $self = shift;
1418  my $tmpdir = $self->{tmpdir};
1419
1420  my $config_file = "$tmpdir/sftp.conf";
1421  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
1422  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
1423
1424  my $log_file = test_get_logfile();
1425
1426  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
1427  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
1428
1429  my $user = 'proftpd';
1430  my $passwd = 'test';
1431  my $group = 'ftpd';
1432  my $home_dir = File::Spec->rel2abs($tmpdir);
1433  my $uid = 500;
1434  my $gid = 500;
1435
1436  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
1437
1438  my $dsa_rfc4716_data = '
1439---- BEGIN SSH2 PUBLIC KEY ----
1440Comment: "1024-bit DSA, converted from OpenSSH by tj@familiar"
1441AAAAB3NzaC1kc3MAAACBAJWsBFKoQ1HdluDnVacaPm+PDPuXAMxwpplFYafjDCye5Y2FZE
1442jSA8GlLAsEk3XCw6JK2+ciE0I/XXn3+3cAkrdjDKQDRn8IcAANatgLSSjxS9XN4oNzKtrj
1443Ss3hOhv5ADhwKMcIhwSSf0cVRH9sGjQF3IiJBVnQjz6i//v+97otAAAAFQDqbZr3aGXlY0
1444Q3UYS3XRNV8ZdWLwAAAIBVZ00AvPF6Kh9GUvXdUAEtNfe1JIThzC4rSc2Fyz3/mQA+GLUH
1445tEq1ZLpO5D4PCjxHcR7N1tIarqR1f0GGjDGvaPocPNtMpaVxCsLWTCnua5fhIgZ3H24mSz
1446d/j2TSDqIeV0DWWiWsFOTF+UzbxSDAinfDjLGV0XQ1jRhgoHS3hAAAAIAfONFEnSPWVLEl
14470Hv9yAozdWBmkyDijkk0zWWGh17z/Ef4ZRo5bwjsOQCx3c3XswdjDacoqUjep8EMs8MI4L
1448pOx8SybGOGu8xyW3ceT+rdP1/S62JxBeL7SaIwCH0O9sPqeh44l8OHIKVh6lmyUr1KQFOn
1449NJ/pRF0JutY1UDEUMQ==
1450---- END SSH2 PUBLIC KEY ----
1451';
1452
1453  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
1454
1455  my $fh;
1456  if (open($fh, "> $db_script")) {
1457    print $fh <<EOS;
1458CREATE TABLE sftpuserkeys (
1459  name TEXT NOT NULL PRIMARY KEY,
1460  key BLOB NOT NULL
1461);
1462
1463INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$dsa_rfc4716_data');
1464EOS
1465    unless (close($fh)) {
1466      die("Can't write $db_script: $!");
1467    }
1468
1469  } else {
1470    die("Can't open $db_script: $!");
1471  }
1472
1473  my $cmd = "sqlite3 $db_file < $db_script";
1474  if ($ENV{TEST_VERBOSE}) {
1475    print STDERR "Executing sqlite3: $cmd\n";
1476  }
1477
1478  my @output = `$cmd`;
1479
1480  unlink($db_script);
1481
1482  # Make sure that, if we're running as root, that the home directory has
1483  # permissions/privs set for the account we create
1484  if ($< == 0) {
1485    unless (chmod(0755, $home_dir)) {
1486      die("Can't set perms on $home_dir to 0755: $!");
1487    }
1488
1489    unless (chown($uid, $gid, $home_dir)) {
1490      die("Can't set owner of $home_dir to $uid/$gid: $!");
1491    }
1492  }
1493
1494  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
1495    '/bin/bash');
1496  auth_group_write($auth_group_file, $group, $gid, $user);
1497
1498  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
1499  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
1500
1501  my $dsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_dsa_key');
1502  my $dsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_dsa_key.pub');
1503
1504  my $config = {
1505    PidFile => $pid_file,
1506    ScoreboardFile => $scoreboard_file,
1507    SystemLog => $log_file,
1508    TraceLog => $log_file,
1509    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
1510
1511    AuthUserFile => $auth_user_file,
1512    AuthGroupFile => $auth_group_file,
1513
1514    IfModules => {
1515      'mod_delay.c' => {
1516        DelayEngine => 'off',
1517      },
1518
1519      'mod_sql_sqlite.c' => {
1520        SQLAuthenticate => 'off',
1521        SQLConnectInfo => $db_file,
1522        SQLLogFile => $log_file,
1523        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
1524      },
1525
1526      'mod_sftp.c' => [
1527        "SFTPEngine on",
1528        "SFTPLog $log_file",
1529        "SFTPHostKey $rsa_host_key",
1530        "SFTPHostKey $dsa_host_key",
1531        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
1532      ],
1533    },
1534  };
1535
1536  my ($port, $config_user, $config_group) = config_write($config_file, $config);
1537
1538  # Open pipes, for use between the parent and child processes.  Specifically,
1539  # the child will indicate when it's done with its test by writing a message
1540  # to the parent.
1541  my ($rfh, $wfh);
1542  unless (pipe($rfh, $wfh)) {
1543    die("Can't open pipe: $!");
1544  }
1545
1546  require Net::SSH2;
1547
1548  my $ex;
1549
1550  # Fork child
1551  $self->handle_sigchld();
1552  defined(my $pid = fork()) or die("Can't fork: $!");
1553  if ($pid) {
1554    eval {
1555      my $ssh2 = Net::SSH2->new();
1556
1557      sleep(1);
1558
1559      unless ($ssh2->connect('127.0.0.1', $port)) {
1560        my ($err_code, $err_name, $err_str) = $ssh2->error();
1561        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
1562      }
1563
1564      unless ($ssh2->auth_publickey($user, $dsa_pub_key, $dsa_priv_key)) {
1565        my ($err_code, $err_name, $err_str) = $ssh2->error();
1566        die("DSA publickey authentication failed: [$err_name] ($err_code) $err_str");
1567      }
1568
1569      $ssh2->disconnect();
1570    };
1571
1572    if ($@) {
1573      $ex = $@;
1574    }
1575
1576    $wfh->print("done\n");
1577    $wfh->flush();
1578
1579  } else {
1580    eval { server_wait($config_file, $rfh) };
1581    if ($@) {
1582      warn($@);
1583      exit 1;
1584    }
1585
1586    exit 0;
1587  }
1588
1589  # Stop server
1590  server_stop($pid_file);
1591
1592  $self->assert_child_ok($pid);
1593
1594  if ($ex) {
1595    test_append_logfile($log_file, $ex);
1596    unlink($log_file);
1597
1598    die($ex);
1599  }
1600
1601  unlink($log_file, $db_file);
1602}
1603
1604sub ssh2_auth_publickey_rsa_dsa_sql_rfc4716 {
1605  my $self = shift;
1606  my $tmpdir = $self->{tmpdir};
1607
1608  my $config_file = "$tmpdir/sftp.conf";
1609  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
1610  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
1611
1612  my $log_file = test_get_logfile();
1613
1614  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
1615  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
1616
1617  my $user = 'proftpd';
1618  my $passwd = 'test';
1619  my $group = 'ftpd';
1620  my $home_dir = File::Spec->rel2abs($tmpdir);
1621  my $uid = 500;
1622  my $gid = 500;
1623
1624  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
1625
1626  my $rsa_rfc4716_data = '---- BEGIN SSH2 PUBLIC KEY ----
1627Comment: "2048-bit RSA, converted from OpenSSH by tj@familiar"
1628AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7j
1629Gx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00y
1630dqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84u
1631O6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMm
1632ef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPk
1633Byq2pv4VBo953gK7f1AQ==
1634---- END SSH2 PUBLIC KEY ----';
1635  my $dsa_rfc4716_data = '
1636---- BEGIN SSH2 PUBLIC KEY ----
1637Comment: "1024-bit DSA, converted from OpenSSH by tj@familiar"
1638AAAAB3NzaC1kc3MAAACBAJWsBFKoQ1HdluDnVacaPm+PDPuXAMxwpplFYafjDCye5Y2FZE
1639jSA8GlLAsEk3XCw6JK2+ciE0I/XXn3+3cAkrdjDKQDRn8IcAANatgLSSjxS9XN4oNzKtrj
1640Ss3hOhv5ADhwKMcIhwSSf0cVRH9sGjQF3IiJBVnQjz6i//v+97otAAAAFQDqbZr3aGXlY0
1641Q3UYS3XRNV8ZdWLwAAAIBVZ00AvPF6Kh9GUvXdUAEtNfe1JIThzC4rSc2Fyz3/mQA+GLUH
1642tEq1ZLpO5D4PCjxHcR7N1tIarqR1f0GGjDGvaPocPNtMpaVxCsLWTCnua5fhIgZ3H24mSz
1643d/j2TSDqIeV0DWWiWsFOTF+UzbxSDAinfDjLGV0XQ1jRhgoHS3hAAAAIAfONFEnSPWVLEl
16440Hv9yAozdWBmkyDijkk0zWWGh17z/Ef4ZRo5bwjsOQCx3c3XswdjDacoqUjep8EMs8MI4L
1645pOx8SybGOGu8xyW3ceT+rdP1/S62JxBeL7SaIwCH0O9sPqeh44l8OHIKVh6lmyUr1KQFOn
1646NJ/pRF0JutY1UDEUMQ==
1647---- END SSH2 PUBLIC KEY ----
1648';
1649
1650  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
1651
1652  my $fh;
1653  if (open($fh, "> $db_script")) {
1654    print $fh <<EOS;
1655CREATE TABLE sftpuserkeys (
1656  name TEXT NOT NULL,
1657  key BLOB NOT NULL
1658);
1659
1660INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_rfc4716_data');
1661INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$dsa_rfc4716_data');
1662EOS
1663    unless (close($fh)) {
1664      die("Can't write $db_script: $!");
1665    }
1666
1667  } else {
1668    die("Can't open $db_script: $!");
1669  }
1670
1671  my $cmd = "sqlite3 $db_file < $db_script";
1672  if ($ENV{TEST_VERBOSE}) {
1673    print STDERR "Executing sqlite3: $cmd\n";
1674  }
1675
1676  my @output = `$cmd`;
1677
1678  unlink($db_script);
1679
1680  # Make sure that, if we're running as root, that the home directory has
1681  # permissions/privs set for the account we create
1682  if ($< == 0) {
1683    unless (chmod(0755, $home_dir)) {
1684      die("Can't set perms on $home_dir to 0755: $!");
1685    }
1686
1687    unless (chown($uid, $gid, $home_dir)) {
1688      die("Can't set owner of $home_dir to $uid/$gid: $!");
1689    }
1690  }
1691
1692  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
1693    '/bin/bash');
1694  auth_group_write($auth_group_file, $group, $gid, $user);
1695
1696  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
1697  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
1698
1699  my $dsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_dsa_key');
1700  my $dsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_dsa_key.pub');
1701
1702  my $config = {
1703    PidFile => $pid_file,
1704    ScoreboardFile => $scoreboard_file,
1705    SystemLog => $log_file,
1706    TraceLog => $log_file,
1707    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
1708
1709    AuthUserFile => $auth_user_file,
1710    AuthGroupFile => $auth_group_file,
1711
1712    IfModules => {
1713      'mod_delay.c' => {
1714        DelayEngine => 'off',
1715      },
1716
1717      'mod_sql_sqlite.c' => {
1718        SQLAuthenticate => 'off',
1719        SQLConnectInfo => $db_file,
1720        SQLLogFile => $log_file,
1721        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
1722      },
1723
1724      'mod_sftp.c' => [
1725        "SFTPEngine on",
1726        "SFTPLog $log_file",
1727        "SFTPHostKey $rsa_host_key",
1728        "SFTPHostKey $dsa_host_key",
1729        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
1730      ],
1731    },
1732  };
1733
1734  my ($port, $config_user, $config_group) = config_write($config_file, $config);
1735
1736  # Open pipes, for use between the parent and child processes.  Specifically,
1737  # the child will indicate when it's done with its test by writing a message
1738  # to the parent.
1739  my ($rfh, $wfh);
1740  unless (pipe($rfh, $wfh)) {
1741    die("Can't open pipe: $!");
1742  }
1743
1744  require Net::SSH2;
1745
1746  my $ex;
1747
1748  # Fork child
1749  $self->handle_sigchld();
1750  defined(my $pid = fork()) or die("Can't fork: $!");
1751  if ($pid) {
1752    eval {
1753      my $ssh2 = Net::SSH2->new();
1754
1755      sleep(1);
1756
1757      unless ($ssh2->connect('127.0.0.1', $port)) {
1758        my ($err_code, $err_name, $err_str) = $ssh2->error();
1759        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
1760      }
1761
1762      unless ($ssh2->auth_publickey($user, $dsa_pub_key, $dsa_priv_key)) {
1763        my ($err_code, $err_name, $err_str) = $ssh2->error();
1764        die("DSA publickey authentication failed: [$err_name] ($err_code) $err_str");
1765      }
1766
1767      $ssh2->disconnect();
1768    };
1769
1770    if ($@) {
1771      $ex = $@;
1772    }
1773
1774    $wfh->print("done\n");
1775    $wfh->flush();
1776
1777  } else {
1778    eval { server_wait($config_file, $rfh) };
1779    if ($@) {
1780      warn($@);
1781      exit 1;
1782    }
1783
1784    exit 0;
1785  }
1786
1787  # Stop server
1788  server_stop($pid_file);
1789
1790  $self->assert_child_ok($pid);
1791
1792  if ($ex) {
1793    test_append_logfile($log_file, $ex);
1794    unlink($log_file);
1795
1796    die($ex);
1797  }
1798
1799  unlink($log_file, $db_file);
1800}
1801
1802sub ssh2_auth_publickey_multiple_keys_one_row_bug3942 {
1803  my $self = shift;
1804  my $tmpdir = $self->{tmpdir};
1805
1806  my $config_file = "$tmpdir/sftp.conf";
1807  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
1808  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
1809
1810  my $log_file = test_get_logfile();
1811
1812  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
1813  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
1814
1815  my $user = 'proftpd';
1816  my $passwd = 'test';
1817  my $group = 'ftpd';
1818  my $home_dir = File::Spec->rel2abs($tmpdir);
1819  my $uid = 500;
1820  my $gid = 500;
1821
1822  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
1823
1824  my $rsa_rfc4716_data1 = '---- BEGIN SSH2 PUBLIC KEY ----
1825Comment: "2048-bit RSA, converted from OpenSSH by tj@familiar"
1826AAAAB3NzaC1yc2EAAAABIwAAAQEAvEm0Jex6M9GBulB6KsOAUR8uk1CCKjx1o2GV8qkOMP
1827Im3sL5642FD2ECoA73zcWs5XktcO72lrI8QxhQmz0Ob7PjobjQq209QoivUsQz9UnupDW1
1828zd9V7tH+ibmslD+LnglfML0WnGLsmvmY3VVJ1dKgXVrxDszhKIWc/QEs2QD9UzmQweBV/7
1829/tYPfVTUnW2THa66zACPdGTqtncy1MxkauSluHsLJ7eDf3g5Vx9BbxgDlavpEa9uuHjEqx
1830An+P2JFm2EKeuqg3rtLNzTt/u4XB/zSEfl/ua1zynSnOxghpE/QDGjuj9hrgGp9OXyfuOZ
1831gG0qd5fdWj6kccmG4PXw==
1832---- END SSH2 PUBLIC KEY ----
1833';
1834
1835  my $rsa_rfc4716_data2 = '---- BEGIN SSH2 PUBLIC KEY ----
1836Comment: "2048-bit RSA, converted from OpenSSH by tj@familiar"
1837AAAAB3NzaC1yc2EAAAABIwAAAQEA1MDOdQ8ddQGd0hNPbO14zFAD1/c0Ontkw3egGGuVDm
183848VTnDNWGWbH5CirShUhjfLzxZkStyepdKFsYXZOeyBaHdqMfEhXhWZ+M7z9B9rUBM6R7W
1839G34v7pzd8bOYDbff25PCITNYk9m/2ZGrFgAK5EChZ9jtxmaqhYWl6xKLilXYkmhId66TTq
1840MgPUrM1sH9QeFV2axQmK1SVEkSzYTaY8WePds5D5cmZLmABAT3UYPQCcrOahISyKazJ9E+
1841YjoMl9GoniSEiHTPK+XfyND83zIihJO16VxUVUMStR5yHBd133SVar4yKo8fv9wfgOxDcf
1842GLxgWrkgXv/3qR/8zNaQ==
1843---- END SSH2 PUBLIC KEY ----
1844';
1845
1846  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
1847
1848  my $fh;
1849  if (open($fh, "> $db_script")) {
1850    print $fh <<EOS;
1851CREATE TABLE sftpuserkeys (
1852  name TEXT NOT NULL PRIMARY KEY,
1853  key BLOB NOT NULL
1854);
1855
1856INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_rfc4716_data1$rsa_rfc4716_data2');
1857EOS
1858    unless (close($fh)) {
1859      die("Can't write $db_script: $!");
1860    }
1861
1862  } else {
1863    die("Can't open $db_script: $!");
1864  }
1865
1866  my $cmd = "sqlite3 $db_file < $db_script";
1867  if ($ENV{TEST_VERBOSE}) {
1868    print STDERR "Executing sqlite3: $cmd\n";
1869  }
1870
1871  my @output = `$cmd`;
1872  if (scalar(@output) &&
1873      $ENV{TEST_VERBOSE}) {
1874    print STDERR "Output: ", join('', @output), "\n";
1875  }
1876
1877  if ($? != 0) {
1878    die("'$cmd' failed");
1879  }
1880
1881  unlink($db_script);
1882
1883  # Make sure that, if we're running as root, that the home directory has
1884  # permissions/privs set for the account we create
1885  if ($< == 0) {
1886    unless (chmod(0755, $home_dir)) {
1887      die("Can't set perms on $home_dir to 0755: $!");
1888    }
1889
1890    unless (chown($uid, $gid, $home_dir)) {
1891      die("Can't set owner of $home_dir to $uid/$gid: $!");
1892    }
1893  }
1894
1895  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
1896    '/bin/bash');
1897  auth_group_write($auth_group_file, $group, $gid, $user);
1898
1899  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
1900  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
1901
1902  my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa2048_key2');
1903  my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa2048_key2.pub');
1904
1905  my $config = {
1906    PidFile => $pid_file,
1907    ScoreboardFile => $scoreboard_file,
1908    SystemLog => $log_file,
1909    TraceLog => $log_file,
1910    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
1911
1912    AuthUserFile => $auth_user_file,
1913    AuthGroupFile => $auth_group_file,
1914
1915    IfModules => {
1916      'mod_delay.c' => {
1917        DelayEngine => 'off',
1918      },
1919
1920      'mod_sql_sqlite.c' => {
1921        SQLAuthenticate => 'off',
1922        SQLConnectInfo => $db_file,
1923        SQLLogFile => $log_file,
1924        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
1925      },
1926
1927      'mod_sftp.c' => [
1928        "SFTPEngine on",
1929        "SFTPLog $log_file",
1930        "SFTPHostKey $rsa_host_key",
1931        "SFTPHostKey $dsa_host_key",
1932        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
1933      ],
1934    },
1935  };
1936
1937  my ($port, $config_user, $config_group) = config_write($config_file, $config);
1938
1939  # Open pipes, for use between the parent and child processes.  Specifically,
1940  # the child will indicate when it's done with its test by writing a message
1941  # to the parent.
1942  my ($rfh, $wfh);
1943  unless (pipe($rfh, $wfh)) {
1944    die("Can't open pipe: $!");
1945  }
1946
1947  require Net::SSH2;
1948
1949  my $ex;
1950
1951  # Fork child
1952  $self->handle_sigchld();
1953  defined(my $pid = fork()) or die("Can't fork: $!");
1954  if ($pid) {
1955    eval {
1956      my $ssh2 = Net::SSH2->new();
1957
1958      sleep(3);
1959
1960      unless ($ssh2->connect('127.0.0.1', $port)) {
1961        my ($err_code, $err_name, $err_str) = $ssh2->error();
1962        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
1963      }
1964
1965      unless ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) {
1966        my ($err_code, $err_name, $err_str) = $ssh2->error();
1967        die("RSA publickey authentication failed: [$err_name] ($err_code) $err_str");
1968      }
1969
1970      $ssh2->disconnect();
1971    };
1972
1973    if ($@) {
1974      $ex = $@;
1975    }
1976
1977    $wfh->print("done\n");
1978    $wfh->flush();
1979
1980  } else {
1981    eval { server_wait($config_file, $rfh) };
1982    if ($@) {
1983      warn($@);
1984      exit 1;
1985    }
1986
1987    exit 0;
1988  }
1989
1990  # Stop server
1991  server_stop($pid_file);
1992
1993  $self->assert_child_ok($pid);
1994
1995  if ($ex) {
1996    test_append_logfile($log_file, $ex);
1997    unlink($log_file);
1998
1999    die($ex);
2000  }
2001
2002  unlink($log_file, $db_file);
2003}
2004
2005sub get_sessions {
2006  my $db_file = shift;
2007  my $where = shift;
2008
2009  my $sql = "SELECT user, key_fingerprint, key_fingerprint_algo FROM sftpsessions";
2010  if ($where) {
2011    $sql .= " WHERE $where";
2012  }
2013
2014  my $cmd = "sqlite3 $db_file \"$sql\"";
2015
2016  if ($ENV{TEST_VERBOSE}) {
2017    print STDERR "Executing sqlite3: $cmd\n";
2018  }
2019
2020  my $res = join('', `$cmd`);
2021  chomp($res);
2022
2023  # The default sqlite3 delimiter is '|'
2024  return split(/\|/, $res);
2025}
2026
2027sub ssh2_auth_publickey_rsa_sql_fp_env_vars {
2028  my $self = shift;
2029  my $tmpdir = $self->{tmpdir};
2030
2031  my $config_file = "$tmpdir/sftp.conf";
2032  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
2033  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
2034
2035  my $log_file = test_get_logfile();
2036
2037  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
2038  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
2039
2040  my $user = 'proftpd';
2041  my $passwd = 'test';
2042  my $group = 'ftpd';
2043  my $home_dir = File::Spec->rel2abs($tmpdir);
2044  my $uid = 500;
2045  my $gid = 500;
2046
2047  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
2048
2049  my $rsa_data = 'AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7jGx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00ydqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84uO6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMmef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPkByq2pv4VBo953gK7f1AQ==';
2050
2051  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
2052
2053  my $fh;
2054  if (open($fh, "> $db_script")) {
2055    print $fh <<EOS;
2056CREATE TABLE sftpuserkeys (
2057  name TEXT NOT NULL PRIMARY KEY,
2058  key BLOB NOT NULL
2059);
2060
2061INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_data');
2062
2063CREATE TABLE sftpsessions (
2064  user TEXT NOT NULL PRIMARY KEY,
2065  key_fingerprint TEXT,
2066  key_fingerprint_algo TEXT
2067);
2068EOS
2069    unless (close($fh)) {
2070      die("Can't write $db_script: $!");
2071    }
2072
2073  } else {
2074    die("Can't open $db_script: $!");
2075  }
2076
2077  my $cmd = "sqlite3 $db_file < $db_script";
2078  if ($ENV{TEST_VERBOSE}) {
2079    print STDERR "Executing sqlite3: $cmd\n";
2080  }
2081
2082  my @output = `$cmd`;
2083
2084  unlink($db_script);
2085
2086  # Make sure that, if we're running as root, that the home directory has
2087  # permissions/privs set for the account we create
2088  if ($< == 0) {
2089    unless (chmod(0755, $home_dir)) {
2090      die("Can't set perms on $home_dir to 0755: $!");
2091    }
2092
2093    unless (chown($uid, $gid, $home_dir)) {
2094      die("Can't set owner of $home_dir to $uid/$gid: $!");
2095    }
2096  }
2097
2098  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
2099    '/bin/bash');
2100  auth_group_write($auth_group_file, $group, $gid, $user);
2101
2102  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
2103  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
2104
2105  my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key');
2106  my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub');
2107
2108  my $config = {
2109    PidFile => $pid_file,
2110    ScoreboardFile => $scoreboard_file,
2111    SystemLog => $log_file,
2112    TraceLog => $log_file,
2113    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
2114
2115    AuthUserFile => $auth_user_file,
2116    AuthGroupFile => $auth_group_file,
2117
2118    IfModules => {
2119      'mod_delay.c' => {
2120        DelayEngine => 'off',
2121      },
2122
2123      'mod_sql_sqlite.c' => [
2124        'SQLAuthenticate off',
2125        "SQLConnectInfo $db_file",
2126        "SQLLogFile $log_file",
2127        'SQLNamedQuery get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
2128        'SQLNamedQuery log_user_key FREEFORM "INSERT INTO sftpsessions (user, key_fingerprint, key_fingerprint_algo) VALUES (\'%u\', \'%{env:SFTP_USER_PUBLICKEY_FINGERPRINT}\', \'%{env:SFTP_USER_PUBLICKEY_FINGERPRINT_ALGO}\')"',
2129        'SQLLog INIT log_user_key',
2130      ],
2131
2132      'mod_sftp.c' => [
2133        "SFTPEngine on",
2134        "SFTPLog $log_file",
2135        "SFTPHostKey $rsa_host_key",
2136        "SFTPHostKey $dsa_host_key",
2137        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
2138      ],
2139    },
2140  };
2141
2142  my ($port, $config_user, $config_group) = config_write($config_file, $config);
2143
2144  # Open pipes, for use between the parent and child processes.  Specifically,
2145  # the child will indicate when it's done with its test by writing a message
2146  # to the parent.
2147  my ($rfh, $wfh);
2148  unless (pipe($rfh, $wfh)) {
2149    die("Can't open pipe: $!");
2150  }
2151
2152  require Net::SSH2;
2153
2154  my $ex;
2155
2156  # Fork child
2157  $self->handle_sigchld();
2158  defined(my $pid = fork()) or die("Can't fork: $!");
2159  if ($pid) {
2160    eval {
2161      my $ssh2 = Net::SSH2->new();
2162
2163      sleep(1);
2164
2165      unless ($ssh2->connect('127.0.0.1', $port)) {
2166        my ($err_code, $err_name, $err_str) = $ssh2->error();
2167        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
2168      }
2169
2170      unless ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) {
2171        my ($err_code, $err_name, $err_str) = $ssh2->error();
2172        die("RSA publickey authentication failed: [$err_name] ($err_code) $err_str");
2173      }
2174
2175      my $sftp = $ssh2->sftp();
2176      unless ($sftp) {
2177        my ($err_code, $err_name, $err_str) = $ssh2->error();
2178        die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
2179      }
2180
2181      $sftp = undef;
2182
2183      $ssh2->disconnect();
2184    };
2185
2186    if ($@) {
2187      $ex = $@;
2188    }
2189
2190    $wfh->print("done\n");
2191    $wfh->flush();
2192
2193  } else {
2194    eval { server_wait($config_file, $rfh) };
2195    if ($@) {
2196      warn($@);
2197      exit 1;
2198    }
2199
2200    exit 0;
2201  }
2202
2203  # Stop server
2204  server_stop($pid_file);
2205
2206  $self->assert_child_ok($pid);
2207
2208  if ($ex) {
2209    test_append_logfile($log_file, $ex);
2210    unlink($log_file);
2211
2212    die($ex);
2213  }
2214
2215  my ($login, $key_fp, $key_fp_algo) = get_sessions($db_file,
2216    "user = \'$user\'");
2217
2218  my $expected;
2219
2220  $expected = $user;
2221  $self->assert($expected eq $login,
2222    test_msg("Expected user '$expected', got '$login'"));
2223
2224  # The value here depends on the version of OpenSSL we use
2225  my $expected_md5 = 'b8:ce:c2:e8:e8:9c:f7:93:11:a4:79:c2:48:64:19:45';
2226  my $expected_sha256 = 'ad:13:cf:f3:07:f4:1f:20:95:44:e5:71:d9:e9:3c:9c:fa:4b:2a:d1:0d:90:fb:1f:a5:0e:77:ea:c1:91:f9:37';
2227  $self->assert($expected_md5 eq $key_fp || $expected_sha256 eq $key_fp,
2228    test_msg("Expected key fingerprint '$expected_md5' or '$expected_sha256', got '$key_fp'"));
2229
2230  $expected_md5 = 'MD5';
2231  $expected_sha256 = 'SHA256';
2232  $self->assert($expected_md5 eq $key_fp_algo || $expected_sha256 eq $key_fp_algo,
2233    test_msg("Expected '$expected_md5' or '$expected_sha256', got '$key_fp_algo'"));
2234
2235  unlink($log_file, $db_file);
2236}
2237
2238sub ssh2_auth_publickey_rsa_sql_rfc4716_overlong_comment_bug4155 {
2239  my $self = shift;
2240  my $tmpdir = $self->{tmpdir};
2241
2242  my $config_file = "$tmpdir/sftp.conf";
2243  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
2244  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
2245
2246  my $log_file = test_get_logfile();
2247
2248  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
2249  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
2250
2251  my $user = 'proftpd';
2252  my $passwd = 'test';
2253  my $group = 'ftpd';
2254  my $home_dir = File::Spec->rel2abs($tmpdir);
2255  my $uid = 500;
2256  my $gid = 500;
2257
2258  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
2259
2260  my $rsa_rfc4716_data = '---- BEGIN SSH2 PUBLIC KEY ----
2261Comment: "2048-bit RSA, converted from OpenSSH by jbaird@fc-qaftp01.corp.follett.com"
2262AAAAB3NzaC1yc2EAAAABIwAAAQEA13H33uYHCPKX+any43mlzsjxrZuFpgdACmCuPa90Kh
2263Xe6hIg6rx5nNLMOuKHfpMEshCQnj9zmtjSGyLZ9ufJv6Wg3SSHTIKQW2HtR9MLM8zzVXDE
2264pcsWQUbwAs7mBdYKlOJxFP3J4PMVAiJe+GnQ889nXkdixB4SRU6LCfrPwg5c1Ho5FOPYys
2265eAxMNjgsR1n8NUDg5COxlktnR+Tunlu/S/7TgcLi+ugvIIEB5vlhaHEZoPIpz2fl15l9FY
2266ueYvzU73ESvUgdNQE16RmKpdmr6WwN9g5mG+tQCMrhWCkk4IAo5gUlx/Go1Osgp2r0ouj1
2267MSJJkwubawXDDPj/RUjw==
2268---- END SSH2 PUBLIC KEY ----';
2269
2270  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
2271
2272  my $fh;
2273  if (open($fh, "> $db_script")) {
2274    print $fh <<EOS;
2275CREATE TABLE sftpuserkeys (
2276  name TEXT NOT NULL PRIMARY KEY,
2277  key BLOB NOT NULL
2278);
2279
2280INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_rfc4716_data');
2281EOS
2282    unless (close($fh)) {
2283      die("Can't write $db_script: $!");
2284    }
2285
2286  } else {
2287    die("Can't open $db_script: $!");
2288  }
2289
2290  my $cmd = "sqlite3 $db_file < $db_script";
2291  if ($ENV{TEST_VERBOSE}) {
2292    print STDERR "Executing sqlite3: $cmd\n";
2293  }
2294
2295  my @output = `$cmd`;
2296
2297  unlink($db_script);
2298
2299  # Make sure that, if we're running as root, that the home directory has
2300  # permissions/privs set for the account we create
2301  if ($< == 0) {
2302    unless (chmod(0755, $home_dir)) {
2303      die("Can't set perms on $home_dir to 0755: $!");
2304    }
2305
2306    unless (chown($uid, $gid, $home_dir)) {
2307      die("Can't set owner of $home_dir to $uid/$gid: $!");
2308    }
2309  }
2310
2311  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
2312    '/bin/bash');
2313  auth_group_write($auth_group_file, $group, $gid, $user);
2314
2315  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
2316  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
2317
2318  my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key_bug4155');
2319  my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key_bug4155.pub');
2320
2321  my $config = {
2322    PidFile => $pid_file,
2323    ScoreboardFile => $scoreboard_file,
2324    SystemLog => $log_file,
2325    TraceLog => $log_file,
2326    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
2327
2328    AuthUserFile => $auth_user_file,
2329    AuthGroupFile => $auth_group_file,
2330
2331    IfModules => {
2332      'mod_delay.c' => {
2333        DelayEngine => 'off',
2334      },
2335
2336      'mod_sql_sqlite.c' => {
2337        SQLAuthenticate => 'off',
2338        SQLConnectInfo => $db_file,
2339        SQLLogFile => $log_file,
2340        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
2341      },
2342
2343      'mod_sftp.c' => [
2344        "SFTPEngine on",
2345        "SFTPLog $log_file",
2346        "SFTPHostKey $rsa_host_key",
2347        "SFTPHostKey $dsa_host_key",
2348        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
2349      ],
2350    },
2351  };
2352
2353  my ($port, $config_user, $config_group) = config_write($config_file, $config);
2354
2355  # Open pipes, for use between the parent and child processes.  Specifically,
2356  # the child will indicate when it's done with its test by writing a message
2357  # to the parent.
2358  my ($rfh, $wfh);
2359  unless (pipe($rfh, $wfh)) {
2360    die("Can't open pipe: $!");
2361  }
2362
2363  require Net::SSH2;
2364
2365  my $ex;
2366
2367  # Fork child
2368  $self->handle_sigchld();
2369  defined(my $pid = fork()) or die("Can't fork: $!");
2370  if ($pid) {
2371    eval {
2372      my $ssh2 = Net::SSH2->new();
2373
2374      sleep(1);
2375
2376      unless ($ssh2->connect('127.0.0.1', $port)) {
2377        my ($err_code, $err_name, $err_str) = $ssh2->error();
2378        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
2379      }
2380
2381      unless ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) {
2382        my ($err_code, $err_name, $err_str) = $ssh2->error();
2383        die("RSA publickey authentication failed: [$err_name] ($err_code) $err_str");
2384      }
2385
2386      $ssh2->disconnect();
2387    };
2388
2389    if ($@) {
2390      $ex = $@;
2391    }
2392
2393    $wfh->print("done\n");
2394    $wfh->flush();
2395
2396  } else {
2397    eval { server_wait($config_file, $rfh) };
2398    if ($@) {
2399      warn($@);
2400      exit 1;
2401    }
2402
2403    exit 0;
2404  }
2405
2406  # Stop server
2407  server_stop($pid_file);
2408
2409  $self->assert_child_ok($pid);
2410
2411  if ($ex) {
2412    test_append_logfile($log_file, $ex);
2413    unlink($log_file);
2414
2415    die($ex);
2416  }
2417
2418  unlink($log_file, $db_file);
2419}
2420
2421sub ssh2_auth_publickey_rsa_sql_invalid_format_bug4350 {
2422  my $self = shift;
2423  my $tmpdir = $self->{tmpdir};
2424
2425  my $config_file = "$tmpdir/sftp.conf";
2426  my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid");
2427  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard");
2428
2429  my $log_file = test_get_logfile();
2430
2431  my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd");
2432  my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group");
2433
2434  my $user = 'proftpd';
2435  my $passwd = 'test';
2436  my $group = 'ftpd';
2437  my $home_dir = File::Spec->rel2abs($tmpdir);
2438  my $uid = 500;
2439  my $gid = 500;
2440
2441  my $db_file = File::Spec->rel2abs("$tmpdir/sftp.db");
2442
2443  my $rsa_data = 'foobar';
2444  my $db_script = File::Spec->rel2abs("$tmpdir/sftp.sql");
2445
2446  my $fh;
2447  if (open($fh, "> $db_script")) {
2448    print $fh <<EOS;
2449CREATE TABLE sftpuserkeys (
2450  name TEXT NOT NULL PRIMARY KEY,
2451  key BLOB NOT NULL
2452);
2453
2454INSERT INTO sftpuserkeys (name, key) VALUES ('$user', '$rsa_data');
2455EOS
2456    unless (close($fh)) {
2457      die("Can't write $db_script: $!");
2458    }
2459
2460  } else {
2461    die("Can't open $db_script: $!");
2462  }
2463
2464  my $cmd = "sqlite3 $db_file < $db_script";
2465  if ($ENV{TEST_VERBOSE}) {
2466    print STDERR "Executing sqlite3: $cmd\n";
2467  }
2468
2469  my @output = `$cmd`;
2470
2471  unlink($db_script);
2472
2473  # Make sure that, if we're running as root, that the home directory has
2474  # permissions/privs set for the account we create
2475  if ($< == 0) {
2476    unless (chmod(0755, $home_dir)) {
2477      die("Can't set perms on $home_dir to 0755: $!");
2478    }
2479
2480    unless (chown($uid, $gid, $home_dir)) {
2481      die("Can't set owner of $home_dir to $uid/$gid: $!");
2482    }
2483  }
2484
2485  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
2486    '/bin/bash');
2487  auth_group_write($auth_group_file, $group, $gid, $user);
2488
2489  my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
2490  my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
2491
2492  my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key_bug4155');
2493  my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key_bug4155.pub');
2494
2495  my $config = {
2496    PidFile => $pid_file,
2497    ScoreboardFile => $scoreboard_file,
2498    SystemLog => $log_file,
2499    TraceLog => $log_file,
2500    Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20',
2501
2502    AuthUserFile => $auth_user_file,
2503    AuthGroupFile => $auth_group_file,
2504
2505    IfModules => {
2506      'mod_delay.c' => {
2507        DelayEngine => 'off',
2508      },
2509
2510      'mod_sql_sqlite.c' => {
2511        SQLAuthenticate => 'off',
2512        SQLConnectInfo => $db_file,
2513        SQLLogFile => $log_file,
2514        SQLNamedQuery => 'get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name = \'%{0}\'"',
2515      },
2516
2517      'mod_sftp.c' => [
2518        "SFTPEngine on",
2519        "SFTPLog $log_file",
2520        "SFTPHostKey $rsa_host_key",
2521        "SFTPHostKey $dsa_host_key",
2522        "SFTPAuthorizedUserKeys sql:/get-user-authorized-keys",
2523      ],
2524    },
2525  };
2526
2527  my ($port, $config_user, $config_group) = config_write($config_file, $config);
2528
2529  # Open pipes, for use between the parent and child processes.  Specifically,
2530  # the child will indicate when it's done with its test by writing a message
2531  # to the parent.
2532  my ($rfh, $wfh);
2533  unless (pipe($rfh, $wfh)) {
2534    die("Can't open pipe: $!");
2535  }
2536
2537  require Net::SSH2;
2538
2539  my $ex;
2540
2541  # Fork child
2542  $self->handle_sigchld();
2543  defined(my $pid = fork()) or die("Can't fork: $!");
2544  if ($pid) {
2545    eval {
2546      my $ssh2 = Net::SSH2->new();
2547
2548      sleep(1);
2549
2550      unless ($ssh2->connect('127.0.0.1', $port)) {
2551        my ($err_code, $err_name, $err_str) = $ssh2->error();
2552        die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str");
2553      }
2554
2555      if ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) {
2556        die("RSA publickey authentication succeeded unexpectedly");
2557      }
2558
2559      $ssh2->disconnect();
2560    };
2561
2562    if ($@) {
2563      $ex = $@;
2564    }
2565
2566    $wfh->print("done\n");
2567    $wfh->flush();
2568
2569  } else {
2570    eval { server_wait($config_file, $rfh) };
2571    if ($@) {
2572      warn($@);
2573      exit 1;
2574    }
2575
2576    exit 0;
2577  }
2578
2579  # Stop server
2580  server_stop($pid_file);
2581
2582  $self->assert_child_ok($pid);
2583
2584  if ($ex) {
2585    test_append_logfile($log_file, $ex);
2586    unlink($log_file);
2587
2588    die($ex);
2589  }
2590
2591  unlink($log_file, $db_file);
2592}
2593
25941;
2595