~ubuntu-branches/ubuntu/lucid/exim4/lucid-updates

« back to all changes in this revision

Viewing changes to .pc/60_convert4r4.dpatch/src/convert4r4.src

  • Committer: Bazaar Package Importer
  • Author(s): Marc Deslauriers
  • Date: 2011-02-08 11:31:29 UTC
  • Revision ID: james.westby@ubuntu.com-20110208113129-ri8y5c2s6hurn80t
Tags: 4.71-3ubuntu1.1
* SECURITY UPDATE: local privilege escalation via alternate config file
  (LP: #697934)
  - debian/patches/80_CVE-2010-4345.patch: backport massive behaviour-
    altering changes from upstream git to fix issue.
  - debian/patches/81_CVE-2010-4345-docs.patch: backport documentation
    changes.
  - debian/patches/67_unnecessaryCopt.dpatch: Do not use exim's -C option
    in utility scripts. This would not work with ALT_CONFIG_PREFIX.
    Patch obtained from Debian's 4.69-9+lenny2.
  - Build with WHITELIST_D_MACROS=OUTGOING. After this security update,
    exim will not regain root privileges (usually necessary for local
    delivery) if the -D option was used. Macro identifiers listed in
    WHITELIST_D_MACROS are exempted from this restriction. mailscanner
    (4.79.11-2.2) uses -DOUTGOING.
  - Build with TRUSTED_CONFIG_LIST=/etc/exim4/trusted_configs. After this
    security update, exim will not re-gain root privileges (usually
    necessary for local delivery) if the -C option was used. This makes
    it impossible to start a fully functional damon with an alternate
    configuration file. /etc/exim4/trusted_configs (can) contain a list
    of filenames (one per line, full path given) to which this
    restriction does not apply.
  - debian/exim4-daemon-*.NEWS: Add description of changes. Thanks to
    Debian and Andreas Metzler for the text.
  - CVE-2010-4345
* SECURITY UPDATE: arbitrary file append via symlink attack (LP: #708023)
  - debian/patches/82_CVE-2011-0017.patch: check setuid and setgid return
    codes in src/exim.c, src/log.c.
  - CVE-2011-0017
* SECURITY UPDATE: denial of service and possible arbitrary code
  execution via hard link to another user's file (LP: #609620)
  - debian/patches/CVE-2010-2023.patch: check for links in
    src/transports/appendfile.c.
  - CVE-2010-2023
* SECURITY UPDATE: denial of service and possible arbitrary code
  execution via symlink on a lock file (LP: #609620)
  - debian/patches/CVE-2010-2024.patch: improve lock file handling in
    src/exim_lock.c, src/transports/appendfile.c.
  - CVE-2010-2024
* debian/rules: disable debconf-updatepo so the security update doesn't
  alter translations.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! PERL_COMMAND -w
 
2
# $Cambridge: exim/exim-src/src/convert4r4.src,v 1.1 2004/10/07 10:39:01 ph10 Exp $
 
3
 
 
4
# This is a Perl script that reads an Exim run-time configuration file for
 
5
# Exim 3. It makes what changes it can for Exim 4, and also output commentary
 
6
# on what it has done, and on things it cannot do.
 
7
 
 
8
# It is assumed that the input is a valid Exim 3 configuration file.
 
9
 
 
10
 
 
11
# These are lists of main options which are abolished in Exim 4.
 
12
# The first contains options that are used to construct new options.
 
13
 
 
14
@skipped_options = (
 
15
"auth_hosts",
 
16
"auth_over_tls_hosts",
 
17
"errors_address",
 
18
"headers_check_syntax",
 
19
"headers_checks_fail",
 
20
"headers_sender_verify",
 
21
"headers_sender_verify_errmsg",
 
22
"host_accept_relay",
 
23
"host_auth_accept_relay",
 
24
"host_reject_recipients",
 
25
"local_domains",
 
26
"local_domains_include_host",
 
27
"local_domains_include_host_literals",
 
28
"log_all_parents",
 
29
"log_arguments",
 
30
"log_incoming_port",
 
31
"log_interface",
 
32
"log_level",
 
33
"log_received_sender",
 
34
"log_received_recipients",
 
35
"log_rewrites",
 
36
"log_sender_on_delivery",
 
37
"log_smtp_confirmation",
 
38
"log_smtp_connections",
 
39
"log_smtp_syntax_errors",
 
40
"log_subject",
 
41
"log_queue_run_level",
 
42
"rbl_domains",
 
43
"rbl_hosts",
 
44
"rbl_reject_recipients",
 
45
"receiver_verify",
 
46
"receiver_verify_addresses",
 
47
"receiver_verify_hosts",
 
48
"receiver_verify_senders",
 
49
"recipients_reject_except",
 
50
"recipients_reject_except_senders",
 
51
"relay_domains",
 
52
"relay_domains_include_local_mx",
 
53
"sender_address_relay",
 
54
"sender_address_relay_hosts",
 
55
"sender_reject_recipients",
 
56
"sender_verify",
 
57
"sender_verify_hosts_callback",
 
58
"sender_verify_callback_domains",
 
59
"sender_verify_callback_timeout",
 
60
"sender_verify_hosts",
 
61
"smtp_etrn_hosts",
 
62
"smtp_expn_hosts",
 
63
"smtp_verify",
 
64
"tls_host_accept_relay",
 
65
"tls_hosts",
 
66
"tls_log_cipher",
 
67
"tls_log_peerdn",
 
68
"tls_verify_ciphers"
 
69
);
 
70
 
 
71
# The second contains options that are completely abolished and have
 
72
# no equivalent.
 
73
 
 
74
@abolished_options = (
 
75
"always_bcc",
 
76
"debug_level",
 
77
"helo_strict_syntax",
 
78
"kill_ip_options",
 
79
"log_ip_options",
 
80
"log_refused_recipients",
 
81
"message_size_limit_count_recipients",
 
82
"rbl_log_headers",
 
83
"rbl_log_rcpt_count",
 
84
"receiver_try_verify",
 
85
"refuse_ip_options",
 
86
"relay_match_host_or_sender",
 
87
"sender_try_verify",
 
88
"sender_verify_batch",
 
89
"sender_verify_fixup",
 
90
"sender_verify_reject",
 
91
"sender_verify_max_retry_rate",
 
92
);
 
93
 
 
94
# This is a list of options that are not otherwise handled, but which
 
95
# contain domain or host lists that have to be processed so that any
 
96
# regular expressions are marked "not for expansion".
 
97
 
 
98
@list_options = (
 
99
"dns_again_means_nonexist",
 
100
"hold_domains",
 
101
"hosts_treat_as_local",
 
102
"percent_hack_domains",
 
103
"queue_smtp_domains",
 
104
"helo_accept_junk_hosts",
 
105
"host_lookup",
 
106
"ignore_fromline_hosts",
 
107
"rfc1413_hosts",
 
108
"sender_unqualified_hosts",
 
109
"smtp_reserve_hosts",
 
110
"tls_advertise_hosts",
 
111
"tls_verify_hosts",
 
112
);
 
113
 
 
114
 
 
115
 
 
116
##################################################
 
117
#          Output problem rubric once            #
 
118
##################################################
 
119
 
 
120
sub rubric {
 
121
return if $rubric_output;
 
122
$rubric_output = 1;
 
123
print STDERR "\n" .
 
124
"** The following comments describe problems that have been encountered\n" .
 
125
"   while converting an Exim 3 runtime file for Exim 4. More detail can\n" .
 
126
"   be found in the file doc/Exim4.upgrade.\n";
 
127
}
 
128
 
 
129
 
 
130
##################################################
 
131
#             Analyse one line                   #
 
132
##################################################
 
133
 
 
134
sub checkline{
 
135
my($line) = $_[0];
 
136
 
 
137
return "comment" if $line =~ /^\s*(#|$)/;
 
138
return "end"     if $line =~ /^\s*end\s*$/i;
 
139
 
 
140
# Macros are recognized only in the first section of the file.
 
141
 
 
142
return "macro" if $prefix eq "" && $line =~ /^\s*[A-Z]/;
 
143
 
 
144
# In retry and rewrite sections, the type is always "other"
 
145
 
 
146
return "other" if $prefix eq "=retry" || $prefix eq "=rewrite";
 
147
 
 
148
# Pick out the name at the start and the rest of the line (into global
 
149
# variables) and return whether the start of a driver or not.
 
150
 
 
151
($hide,$name,$rest) = $line =~ /^\s*(hide\s+|)([a-z0-9_]+)\s*(.*?)\s*$/;
 
152
 
 
153
# If $rest begins with a colon, this is a driver name
 
154
 
 
155
return "driver" if $rest =~ /^:/;
 
156
 
 
157
# If $rest begins with an = the value of the option is given explicitly;
 
158
# remove the = from the start. Turn "yes"/"no" into "true"/"false".
 
159
 
 
160
if ($rest =~ /^=/)
 
161
  {
 
162
  $rest =~ s/^=\s*//;
 
163
  $rest = "true" if $rest eq "yes";
 
164
  $rest = "false" if $rest eq "no";
 
165
  }
 
166
 
 
167
# Otherwise we have a boolean option. Set up a "true"/"false" value.
 
168
 
 
169
else
 
170
  {
 
171
  if ($name =~ /^not?_/)     # Recognize "no_" or "not_"
 
172
    {
 
173
    $rest = "false";
 
174
    $name =~ s/^not?_//;
 
175
    }
 
176
  else
 
177
    {
 
178
    $rest = "true";
 
179
    }
 
180
  }
 
181
 
 
182
return "option";
 
183
}
 
184
 
 
185
 
 
186
 
 
187
##################################################
 
188
#       Negate a list of things                  #
 
189
##################################################
 
190
 
 
191
# Can be tricky, because there may be comment lines in the list.
 
192
# Also, lists may have different delimiters.
 
193
 
 
194
sub negate {
 
195
my($list) = $_[0];
 
196
my($delim) = ":";
 
197
my($leadin) = "";
 
198
 
 
199
return $list if ! defined $list;
 
200
 
 
201
($list) = $list =~ /^"?(.*?)"?\s*$/s;      # Remove surrounding quotes
 
202
$list =~ s/\\\s*\n\s*//g;                  # Remove continuation markers
 
203
 
 
204
if ($list =~ /^(\s*<(\S)\s*)(.*)/s)
 
205
  {
 
206
  $leadin = $1;
 
207
  $delim = $2;
 
208
  $list = $3;
 
209
  }
 
210
 
 
211
$list =~ s/^\s+//;
 
212
$list =~ s/\Q$delim$delim/>%%%%</g;
 
213
@split = split /\s*\Q$delim\E\s*/s, $list;
 
214
 
 
215
foreach $item (@split)
 
216
  {
 
217
  $item =~ s/>%%%%</$delim$delim/g;
 
218
 
 
219
  if ($item =~ /^\s*#/)
 
220
    {
 
221
    $item =~ s/((?:^\s*#[^\n]*\n)+\s*)/$1! /mg;
 
222
    $item =~ s/!\s*!//sg;
 
223
    }
 
224
  else
 
225
    {
 
226
    if ($item =~ /^\s*!(.*)/)
 
227
      { $item = $1; }
 
228
    else
 
229
      { $item = "! " . $item; }
 
230
    }
 
231
  }
 
232
 
 
233
$" = " $delim \\\n    ";
 
234
$leadin .= " " if $leadin !~ /(^|\s)$/;
 
235
return "$leadin@split";
 
236
}
 
237
 
 
238
 
 
239
 
 
240
##################################################
 
241
#   Prevent regex expansion in a list of things  #
 
242
##################################################
 
243
 
 
244
# Can be tricky, because there may be comment lines in the list.
 
245
# Also, lists may have different delimiters.
 
246
 
 
247
sub no_expand_regex {
 
248
my($list) = $_[0];
 
249
my($delim) = ":";
 
250
my($leadin) = "";
 
251
 
 
252
return $list if ! defined $list;
 
253
 
 
254
$delim = $_[1] if (defined $_[1]);
 
255
 
 
256
my($is_route_list) = $delim eq ";";
 
257
 
 
258
($list) = $list =~ /^"?(.*?)"?\s*$/s;      # Remove surrounding quotes
 
259
$list =~ s/\\\s*\n\s*//g;                  # Remove continuation markers
 
260
 
 
261
if ($list =~ /^(\s*<(\S)\s*)(.*)/s)
 
262
  {
 
263
  $leadin = $1;
 
264
  $delim = $2;
 
265
  $list = $3;
 
266
  }
 
267
 
 
268
$list =~ s/^\s+//;
 
269
$list =~ s/\Q$delim$delim/>%%%%</g;
 
270
@split = split /\s*\Q$delim\E\s*/s, $list;
 
271
 
 
272
my($changed) = 0;
 
273
foreach $item (@split)
 
274
  {
 
275
  $item =~ s/>%%%%</$delim$delim/g;
 
276
  if ($item =~ /^\^/)
 
277
    {
 
278
    # Fudge for route_list items
 
279
 
 
280
    if ($is_route_list)
 
281
      {
 
282
      $item = "\\N$item";      # Only one item ...
 
283
      }
 
284
    else
 
285
      {
 
286
      $item = "\\N$item\\N";
 
287
      }
 
288
    $changed = 1;
 
289
    }
 
290
  }
 
291
print STDOUT
 
292
  "#!!# Regular expressions enclosed in \\N...\\N to avoid expansion\n"
 
293
    if $changed;
 
294
 
 
295
$" = " $delim \\\n    ";
 
296
$leadin .= " " if $leadin !~ /(^|\s)$/;
 
297
return "$leadin@split";
 
298
}
 
299
 
 
300
 
 
301
 
 
302
##################################################
 
303
#      Sort out lookups in an address list       #
 
304
##################################################
 
305
 
 
306
# Can be tricky, because there may be comment lines in the list.
 
307
# Also, lists may have different delimiters.
 
308
 
 
309
sub sort_address_list {
 
310
my($list) = $_[0];
 
311
my($name) = $_[1];
 
312
my($delim) = ":";
 
313
my($leadin) = "";
 
314
my($quoted) = 0;
 
315
 
 
316
return $list if ! defined $list;
 
317
 
 
318
if ($list =~ /^"(.*?)"\s*$/s)            # Remove surrounding quotes
 
319
  {
 
320
  $list = $1;
 
321
  $quoted = 1;
 
322
  }
 
323
 
 
324
$list =~ s/\\\s*\n\s*//g;                  # Remove continuation markers
 
325
 
 
326
if ($list =~ /^(\s*<(\S)\s*)(.*)/s)
 
327
  {
 
328
  $leadin = $1;
 
329
  $delim = $2;
 
330
  $list = $3;
 
331
  }
 
332
 
 
333
$list =~ s/^\s+//;
 
334
$list =~ s/\Q$delim$delim/>%%%%</g;
 
335
@split = split /\s*\Q$delim\E\s*/s, $list;
 
336
 
 
337
foreach $item (@split)
 
338
  {
 
339
  $item =~ s/>%%%%</$delim$delim/g;
 
340
  if ($item =~ /^\s*(?:partial-)?(\w+;.*)$/)
 
341
    {
 
342
    my($lookup) = $1;
 
343
    if ($lookup =~ /^lsearch|^dbm|^cdb|^nis[^p]/)
 
344
      {
 
345
      &rubric();
 
346
      print STDERR "\n" .
 
347
"** The Exim 3 \"$name\" option specifies an address\n" .
 
348
"   list that includes the item\n\n" .
 
349
"     $item\n\n" .
 
350
"   In Exim 4 address lists, single-key lookups without a local part just\n" .
 
351
"   look up the complete address. They don't also try the domain, as\n" .
 
352
"   happened in Exim 3. The item has been rewritten as two items to make\n" .
 
353
"   it behave in the same way as Exim 3, but you should check to see if\n" .
 
354
"   this is actually what you want.\n";
 
355
 
 
356
      $item = "*\@$item $delim $lookup";
 
357
      }
 
358
    }
 
359
  }
 
360
 
 
361
$" = " $delim \\\n    ";
 
362
$leadin .= " " if $leadin !~ /(^|\s)$/;
 
363
 
 
364
return $quoted? "\"$leadin@split\"" : "$leadin@split";
 
365
}
 
366
 
 
367
 
 
368
 
 
369
##################################################
 
370
#       Quote a string against expansion         #
 
371
##################################################
 
372
 
 
373
# Used for setting up new "domains" options
 
374
 
 
375
sub expquote {
 
376
my($s) = $_[0];
 
377
$s =~ s/\$/\\\$/sg;
 
378
$s =~ s/\\(?!\s*\n)/\\\\/sg;
 
379
return $s;
 
380
}
 
381
 
 
382
 
 
383
 
 
384
##################################################
 
385
#          Dequote an option string              #
 
386
##################################################
 
387
 
 
388
# If the original list is not quoted, do nothing.
 
389
# If it is quoted, just get rid of the quotes.
 
390
 
 
391
sub unquote {
 
392
my($s) = $_[0];
 
393
$s =~ s/^"(.*)"$/$1/s;
 
394
return $s;
 
395
}
 
396
 
 
397
 
 
398
##################################################
 
399
#      Quote/dequote an option string            #
 
400
##################################################
 
401
 
 
402
# If the original list is not quoted, quote it against expansion.
 
403
# If it is quoted, just get rid of the quotes. Also, indent any
 
404
# continuations.
 
405
 
 
406
sub acl_quote {
 
407
my($s) = $_[0];
 
408
$s = ($s =~ /^"(.*)"$/s)? $1 : &expquote($s);
 
409
$s =~ s/\n/\n  /g;
 
410
$s =~ s/\n\s{11,}/\n           /g;
 
411
return $s;
 
412
}
 
413
 
 
414
 
 
415
##################################################
 
416
#       Handle abolished driver options          #
 
417
##################################################
 
418
 
 
419
sub abolished {
 
420
my($hash) = shift @_;
 
421
my($name) = shift @_;
 
422
for $abolished (@_)
 
423
  {
 
424
  if (defined $$hash{$abolished})
 
425
    {
 
426
    &rubric();
 
427
    print STDERR "\n" .
 
428
"** $name used the \"$abolished\" option, which no\n".
 
429
"   longer exists. The option has been removed.\n";
 
430
    print STDOUT "#!!# $abolished option removed\n";
 
431
    delete $$hash{$abolished};
 
432
    }
 
433
  }
 
434
}
 
435
 
 
436
 
 
437
 
 
438
##################################################
 
439
#        Handle renamed driver options           #
 
440
##################################################
 
441
 
 
442
sub renamed {
 
443
my($hash,$old,$new) = @_;
 
444
if (defined $$hash{$old})
 
445
  {
 
446
  print STDOUT "#!!# $old renamed $new\n";
 
447
  $$hash{$new} = $$hash{$old};
 
448
  delete $$hash{$old};
 
449
  }
 
450
}
 
451
 
 
452
 
 
453
 
 
454
##################################################
 
455
#      Comment on user names in require_files    #
 
456
##################################################
 
457
 
 
458
sub check_require {
 
459
my($string, $name) = @_;
 
460
 
 
461
$string =~ s/::/[[[]]]/g;
 
462
my(@list) = split /:/, $string;
 
463
my($item);
 
464
 
 
465
for $item (@list)
 
466
  {
 
467
  if ($item =~ /^\s*[\w,]+\s*$/)
 
468
    {
 
469
    &rubric();
 
470
    $item =~ s/^\s*//;
 
471
    $item =~ s/\s*$//;
 
472
    print STDERR "\n" .
 
473
"** A setting of require_files in the $name contains\n" .
 
474
"   what appears to be a user name ('$item'). The ability to check files\n" .
 
475
"   as a specific user is done differently in Exim 4. In fact, because the\n" .
 
476
"   routers run as root, you may not need this at all.\n"
 
477
    }
 
478
  }
 
479
}
 
480
 
 
481
 
 
482
##################################################
 
483
#        Handle current and home directory       #
 
484
##################################################
 
485
 
 
486
sub handle_current_and_home_directory {
 
487
my($hash,$driver,$name) = @_;
 
488
 
 
489
for ("current_directory", "home_directory")
 
490
  {
 
491
  if (defined $$hash{$_} && $$hash{$_} eq "check_local_user")
 
492
    {
 
493
    my($article) = (substr($driver, 0, 1) eq "a")? "an" : "a";
 
494
    &rubric();
 
495
    print STDERR "\n" .
 
496
"** The Exim 3 configuration contains $article '$driver' director called\n" .
 
497
"   '$name', which set '$_' to the special value\n" .
 
498
"   'check_local_user'. This facility has been abolished in Exim 4 because\n" .
 
499
"   it is no longer necessary. The setting has therefore been omitted. See\n" .
 
500
"   note X.\n";
 
501
    delete $$hash{$_};
 
502
    }
 
503
  else
 
504
    {
 
505
    &renamed($hash, $_, "transport_$_");
 
506
    }
 
507
  }
 
508
}
 
509
 
 
510
 
 
511
 
 
512
##################################################
 
513
#    Handle batch/bsmtp for appendfile/pipe      #
 
514
##################################################
 
515
 
 
516
sub handle_batch_and_bsmtp{
 
517
my($hash) = @_;
 
518
 
 
519
if (defined $$hash{"bsmtp"})
 
520
  {
 
521
  if ($$hash{"bsmtp"} ne "none")
 
522
    {
 
523
    $$hash{"use_bsmtp"} = "true";
 
524
    $$hash{"message_prefix"} = "\"HELO \$primary_host_name\\n\""
 
525
      if defined $$hash{"bsmtp_helo"} && $$hash{"bsmtp_helo"} eq "true";
 
526
    }
 
527
 
 
528
  if ($$hash{"bsmtp"} eq "one")
 
529
    {
 
530
    delete $$hash{"batch"};
 
531
    }
 
532
  else
 
533
    {
 
534
    $$hash{"batch"} = $$hash{"bsmtp"};
 
535
    }
 
536
 
 
537
  delete $$hash{"bsmtp"};
 
538
  delete $$hash{"bsmtp_helo"};
 
539
  }
 
540
 
 
541
if (defined $$hash{"batch"} && $$hash{"batch"} ne "none")
 
542
  {
 
543
  $$hash{"batch_max"} = "100" if !defined $$hash{"batch_max"};
 
544
  $$hash{"batch_id"} = "\$domain" if $$hash{"batch"} eq "domain";
 
545
  }
 
546
else
 
547
  {
 
548
  $$hash{"batch_max"} = "1" if defined $$hash{"batch_max"};
 
549
  }
 
550
delete $$hash{"batch"};
 
551
}
 
552
 
 
553
 
 
554
 
 
555
##################################################
 
556
#              Output one option                 #
 
557
##################################################
 
558
 
 
559
sub outopt {
 
560
my($hash, $key, $no_expand) = @_;
 
561
my($data) = $$hash{$key};
 
562
 
 
563
print STDOUT "hide " if defined $$hash{"$key-hide"};
 
564
 
 
565
# Output booleans in the form that doesn't use "="
 
566
 
 
567
if ($data eq "true")
 
568
  {
 
569
  print STDOUT "$key\n";
 
570
  }
 
571
elsif ($data eq "false")
 
572
  {
 
573
  print STDOUT "no_$key\n";
 
574
  }
 
575
else
 
576
  {
 
577
  if ($no_expand)
 
578
    {
 
579
    printf STDOUT ("$key = %s\n", &no_expand_regex($data));
 
580
    }
 
581
  else
 
582
    {
 
583
    print STDOUT "$key = $data\n";
 
584
    }
 
585
  }
 
586
}
 
587
 
 
588
 
 
589
 
 
590
##################################################
 
591
#       Output the options for one driver        #
 
592
##################################################
 
593
 
 
594
# Put the "driver" option first
 
595
 
 
596
sub outdriver {
 
597
my($hash) = $_[0];
 
598
print STDOUT "  driver = $$hash{'driver'}\n";
 
599
foreach $key (sort keys %$hash)
 
600
  {
 
601
  next if $key eq "driver" || $key =~ /-hide$/;
 
602
  print STDOUT "  ";
 
603
  &outopt($hash, $key, 0);
 
604
  }
 
605
}
 
606
 
 
607
 
 
608
 
 
609
##################################################
 
610
#      Output a rewrite or a retry line          #
 
611
##################################################
 
612
 
 
613
# These lines start with patterns which are now always expanded. If the
 
614
# pattern is a regex, arrange for it not to expand.
 
615
 
 
616
sub print_no_expand {
 
617
my($s) = $_[0];
 
618
if ($s =~ /^\^/)
 
619
  {
 
620
  if (!$escape_output)
 
621
    {
 
622
    &rubric();
 
623
    print STDERR "\n" .
 
624
"** You have a retry or rewrite pattern that is a regular expression. Because\n" .
 
625
"   these patterns are now always expanded, you need to be sure that the\n" .
 
626
"   special characters in the regex are not interpreted by the expander.\n" .
 
627
"   \\N has been inserted at the start of the regex to prevent the rest of\n" .
 
628
"   it from being expanded.\n";
 
629
    $escape_output = 1;
 
630
    }
 
631
  print STDOUT "\\N";
 
632
  }
 
633
print STDOUT "$s\n";
 
634
}
 
635
 
 
636
 
 
637
 
 
638
##################################################
 
639
#          Test a boolean main option            #
 
640
##################################################
 
641
 
 
642
# This just saves a lot of typing
 
643
 
 
644
sub bool {
 
645
return defined $main{$_[0]} && $main{$_[0]} eq "true";
 
646
}
 
647
 
 
648
 
 
649
 
 
650
##################################################
 
651
#                  Main program                  #
 
652
##################################################
 
653
 
 
654
print STDERR "Runtime configuration file converter for Exim release 4.\n";
 
655
 
 
656
$transport_start = $director_start = $router_start = $retry_start
 
657
  = $rewrite_start = $auth_start = 999999;
 
658
 
 
659
$macro_output = "";
 
660
$rubric_output = 0;
 
661
$errmsg_output = 0;
 
662
$key_output = 0;
 
663
$unk_output = 0;
 
664
$escape_output = 0;
 
665
$add_no_more = 0;
 
666
$add_caseful_local_part = 0;
 
667
$done_dns_check_names = 0;
 
668
 
 
669
$queue_only_load_was_present = 0;
 
670
$deliver_queue_load_max_was_present = 0;
 
671
 
 
672
# Read the entire file into an array
 
673
 
 
674
chomp(@c = <STDIN>);
 
675
$clen = scalar @c;
 
676
 
 
677
# Remove the standard comment that appears at the end of the default
 
678
 
 
679
if ($clen > 0 && $c[$clen-1] =~ /^#\s*End of Exim configuration file\s*/i)
 
680
  {
 
681
  pop @c;
 
682
  $clen--;
 
683
  }
 
684
 
 
685
# The first pass over the input fishes out all the options settings in the
 
686
# main, transport, director, and router sections, and places their values in
 
687
# associative arrays. It also notes the starting position of all the sections.
 
688
 
 
689
$prefix = "";
 
690
%main = ();
 
691
$hash = \%main;
 
692
 
 
693
for ($i = 0; $i < $clen; $i++)
 
694
  {
 
695
  # Change references to +allow_unknown and +warn_unknown into +include_unknown
 
696
 
 
697
  if ($c[$i] =~ /\+(?:allow|warn)_unknown/)
 
698
    {
 
699
    if (!$unk_output)
 
700
      {
 
701
      &rubric();
 
702
      print STDERR "\n" .
 
703
"** You have used '+allow_unknown' or '+warn_unknown' in a configuration\n" .
 
704
"   option. This has been converted to '+include_unknown', but the action\n" .
 
705
"   is different in Exim 4, so you should review all the relevant options.\n";
 
706
      $unk_output = 1;
 
707
      }
 
708
    $c[$i] =~ s/\+(?:allow|warn)_unknown/+include_unknown/g;
 
709
    }
 
710
 
 
711
  # Any reference to $errmsg_recipient is changed to $bounce_recipient
 
712
 
 
713
  if ($c[$i] =~ /\$errmsg_recipient/)
 
714
    {
 
715
    if (!$errmsg_output)
 
716
      {
 
717
      &rubric();
 
718
      print STDERR "\n" .
 
719
"** References to \$errmsg_recipient have been changed to \$bounce_recipient\n";
 
720
      $errmsg_output = 1;
 
721
      }
 
722
    $c[$i] =~ s/\$errmsg_recipient/\$bounce_recipient/g;
 
723
    }
 
724
 
 
725
 
 
726
  # Analyse the type of line
 
727
 
 
728
  $type = &checkline($c[$i]);
 
729
  next if $type eq "comment";
 
730
 
 
731
  # Output a warning if $key is used
 
732
 
 
733
  if ($c[$i] =~ /\$key/ && !$key_output)
 
734
    {
 
735
    &rubric();
 
736
    print STDERR "\n" .
 
737
"** You have used '\$key' in a configuration option. This variable does not\n" .
 
738
"   exist in Exim 4. Instead, the value you need for your lookup will be\n" .
 
739
"   in one of the other variables such as '\$domain' or '\$host'. You will\n" .
 
740
"   need to edit the new configuration to sort this out.\n";
 
741
    $key_output = 1;
 
742
    }
 
743
 
 
744
  # Save macro definitions so we can output them first; must handle
 
745
  # continuations.
 
746
 
 
747
  if ($type eq "macro")
 
748
    {
 
749
    $macro_output .= "$c[$i++]\n" while $c[$i] =~ /\\\s*$|^\s*#/;
 
750
    $macro_output .= "$c[$i]\n";
 
751
    }
 
752
 
 
753
  # Handle end of section
 
754
 
 
755
  elsif ($type eq "end")
 
756
    {
 
757
    if ($prefix eq "=rewrite")
 
758
      {
 
759
      $prefix = "a.";
 
760
      $auth_start = $i + 1;
 
761
      last;
 
762
      }
 
763
    elsif ($prefix eq "=retry")
 
764
      {
 
765
      $prefix = "=rewrite";
 
766
      $rewrite_start = $i + 1;
 
767
      }
 
768
    elsif ($prefix eq "r.")
 
769
      {
 
770
      $prefix = "=retry";
 
771
      $retry_start = $i + 1;
 
772
      }
 
773
    elsif ($prefix eq "d.")
 
774
      {
 
775
      $prefix = "r.";
 
776
      $router_start = $i + 1;
 
777
      }
 
778
    elsif ($prefix eq "t.")
 
779
      {
 
780
      $prefix = "d.";
 
781
      $director_start = $i + 1;
 
782
      }
 
783
    elsif ($prefix eq "")
 
784
      {
 
785
      $prefix = "t.";
 
786
      $transport_start = $i + 1;
 
787
      }
 
788
    }
 
789
 
 
790
  # Handle start of a new director, router or transport driver
 
791
 
 
792
  elsif ($type eq "driver" && $prefix !~ /^=/)
 
793
    {
 
794
    $hash = {};
 
795
    if (defined $driverlist{"$prefix$name"})
 
796
      {
 
797
      die "*** There are two drivers with the name \"$name\"\n";
 
798
      }
 
799
    $driverlist{"$prefix$name"} = $hash;
 
800
    $first_director = $name if !defined $first_director && $prefix eq "d.";
 
801
    }
 
802
 
 
803
  # Handle definition of an option; we must pull in any continuation
 
804
  # strings, and save the value in the current hash. Note if the option
 
805
  # is hidden.
 
806
 
 
807
  elsif ($type eq "option")
 
808
    {
 
809
    my($nextline) = "";
 
810
 
 
811
    while ($i < $clen - 1 && ($rest =~ /\\\s*$/s || $nextline =~ /^\s*#/))
 
812
      {
 
813
      $nextline = $c[++$i];
 
814
      $rest .= "\n$nextline";
 
815
      }
 
816
 
 
817
    $$hash{$name} = $rest;
 
818
    $$hash{"$name-hide"} = 1 if $hide ne "";
 
819
    }
 
820
  }
 
821
 
 
822
 
 
823
# Generate the new configuration. Start with a warning rubric.
 
824
 
 
825
print STDOUT "#!!# This file is output from the convert4r4 script, which tries\n";
 
826
print STDOUT "#!!# to convert Exim 3 configurations into Exim 4 configurations.\n";
 
827
print STDOUT "#!!# However, it is not perfect, especially with non-simple\n";
 
828
print STDOUT "#!!# configurations. You must check it before running it.\n";
 
829
print STDOUT "\n\n";
 
830
 
 
831
# Output the macro definitions
 
832
 
 
833
if ($macro_output ne "")
 
834
  {
 
835
  print STDOUT "#!!# All macro definitions have been gathered here to ensure\n";
 
836
  print STDOUT "#!!# they precede any references to them.\n\n";
 
837
  print STDOUT "$macro_output\n";
 
838
  }
 
839
 
 
840
# Output some default pointers to ACLs for RCPT and DATA time. If no Exim 3
 
841
# options that apply are set, non-restricting ACLs are generated.
 
842
 
 
843
print STDOUT "#!!# These options specify the Access Control Lists (ACLs) that\n";
 
844
print STDOUT "#!!# are used for incoming SMTP messages - after the RCPT and DATA\n";
 
845
print STDOUT "#!!# commands, respectively.\n\n";
 
846
 
 
847
print STDOUT "acl_smtp_rcpt = check_recipient\n";
 
848
print STDOUT "acl_smtp_data = check_message\n\n";
 
849
 
 
850
if (defined $main{"auth_over_tls_hosts"})
 
851
  {
 
852
  print STDOUT "#!!# This option specifies the Access Control List (ACL) that\n";
 
853
  print STDOUT "#!!# is used after an AUTH command.\n\n";
 
854
  print STDOUT "acl_smtp_auth = check_auth\n\n";
 
855
  }
 
856
 
 
857
if (&bool("smtp_verify") ||
 
858
    defined $main{"smtp_etrn_hosts"} ||
 
859
    defined $main{"smtp_expn_hosts"})
 
860
  {
 
861
  print STDOUT "#!!# These options specify the Access Control Lists (ACLs) that\n";
 
862
  print STDOUT "#!!# are used to control the ETRN, EXPN, and VRFY commands.\n";
 
863
  print STDOUT "#!!# Where no ACL is defined, the command is locked out.\n\n";
 
864
 
 
865
  print STDOUT "acl_smtp_etrn = check_etrn\n" if defined $main{"smtp_etrn_hosts"};
 
866
  print STDOUT "acl_smtp_expn = check_expn\n" if defined $main{"smtp_expn_hosts"};
 
867
  print STDOUT "acl_smtp_vrfy = check_vrfy\n" if &bool("smtp_verify");
 
868
  print STDOUT "\n";
 
869
  }
 
870
 
 
871
# If local_domains was set, get its value; otherwise set to "@". Add into it
 
872
# appropriate magic for local_domains_include_host[_literals].
 
873
 
 
874
$local_domains = (defined $main{"local_domains"})? $main{"local_domains"} : "@";
 
875
 
 
876
$ldsep = ":";
 
877
if ($local_domains =~ /^\s*<(.)\s*(.*)/s)
 
878
  {
 
879
  $ldsep = $1;
 
880
  $local_domains = $2;
 
881
  }
 
882
 
 
883
$local_domains = "\@[] $ldsep " . $local_domains
 
884
  if defined $main{"local_domains_include_host_literals"} &&
 
885
     $main{"local_domains_include_host_literals"} eq "true";
 
886
 
 
887
$local_domains = "\@ $ldsep " . $local_domains
 
888
  if defined $main{"local_domains_include_host"} &&
 
889
     $main{"local_domains_include_host"} eq "true";
 
890
 
 
891
$local_domains = "<$ldsep " . $local_domains if $ldsep ne ":";
 
892
 
 
893
# Output a domain list setting for these domains, provided something is defined
 
894
 
 
895
if ($local_domains !~ /^\s*$/)
 
896
  {
 
897
  print STDOUT "#!!# This setting defines a named domain list called\n";
 
898
  print STDOUT "#!!# local_domains, created from the old options that\n";
 
899
  print STDOUT "#!!# referred to local domains. It will be referenced\n";
 
900
  print STDOUT "#!!# later on by the syntax \"+local_domains\".\n";
 
901
  print STDOUT "#!!# Other domain and host lists may follow.\n\n";
 
902
 
 
903
  printf STDOUT ("domainlist local_domains = %s\n\n",
 
904
    &no_expand_regex($local_domains));
 
905
  }
 
906
 
 
907
$relay_domains = (defined $main{"relay_domains"})? $main{"relay_domains"} : "";
 
908
 
 
909
$ldsep = ":";
 
910
if ($relay_domains =~ /^\s*<(.)\s*(.*)/s)
 
911
  {
 
912
  $ldsep = $1;
 
913
  }
 
914
 
 
915
if (defined $main{"relay_domains_include_local_mx"})
 
916
  {
 
917
  $relay_domains .= ($relay_domains =~ /^\s*$/)? "\@mx_any" :
 
918
    " $ldsep \@mx_any";
 
919
  }
 
920
 
 
921
printf STDOUT ("domainlist relay_domains = %s\n",
 
922
  &no_expand_regex($relay_domains))
 
923
    if $relay_domains !~ /^\s*$/;
 
924
 
 
925
 
 
926
# If ignore_errmsg_errors is set, we are going to force 0s as the value
 
927
# for ignore_errmsg_errors_after, so arrange to skip any other value.
 
928
 
 
929
push @skipped_options, "ignore_errmsg_errors_after"
 
930
   if &bool("ignore_errmsg_errors");
 
931
 
 
932
 
 
933
# If rbl_domains is set, split it up and generate six lists:
 
934
#   rbl_warn_domains, rbl_warn_domains_skiprelay
 
935
#   rbl_reject_domains, rbl_reject_domains_skiprelay
 
936
#   rbl_accept_domains, rbl_accept_domains_skiprelay
 
937
 
 
938
if (defined $main{"rbl_domains"})
 
939
  {
 
940
  my($s) = &unquote($main{"rbl_domains"});
 
941
  $s =~ s/\s*\\\s*\n\s*/ /g;
 
942
  my(@list) = split /\s*:\s*/, $s;
 
943
 
 
944
  foreach $d (@list)
 
945
    {
 
946
    my(@sublist) = split /\//, $d;
 
947
    my($name) = shift @sublist;
 
948
    my($warn) = 0;
 
949
    if (defined $main{"rbl_reject_recipients"})
 
950
      {
 
951
      $warn = $main{"rbl_reject_recipients"} ne "true";
 
952
      }
 
953
 
 
954
    foreach $o (@sublist)
 
955
      {
 
956
      $warn = 1 if $o eq "warn";
 
957
      $warn = 0 if $o eq "reject";
 
958
      $warn = 2 if $o eq "accept";
 
959
      $skiprelay = 1 if $o eq "skiprelay";
 
960
      }
 
961
 
 
962
    if ($skiprelay)
 
963
      {
 
964
      if ($warn == 0)
 
965
        {
 
966
        $rbl_reject_skiprelay .= ((defined $rbl_reject_skiprelay)? ":":"").$name;
 
967
        }
 
968
      elsif ($warn == 1)
 
969
        {
 
970
        $rbl_warn_skiprelay .= ((defined $rbl_warn_skiprelay)? ":":"").$name;
 
971
        }
 
972
      elsif ($warn == 2)
 
973
        {
 
974
        $rbl_accept_skiprelay .= ((defined $rbl_accept_skiprelay)? ":":"").$name;
 
975
        }
 
976
      }
 
977
    else
 
978
      {
 
979
      if ($warn == 0)
 
980
        {
 
981
        $rbl_reject_domains .= ((defined $rbl_reject_domains)? ":":"").$name;
 
982
        }
 
983
      elsif ($warn == 1)
 
984
        {
 
985
        $rbl_warn_domains .= ((defined $rbl_warn_domains)? ":":"").$name;
 
986
        }
 
987
      elsif ($warn == 2)
 
988
        {
 
989
        $rbl_accept_domains .= ((defined $rbl_accept_domains)? ":":"").$name;
 
990
        }
 
991
      }
 
992
    }
 
993
  }
 
994
 
 
995
 
 
996
# Output host list settings
 
997
 
 
998
printf STDOUT ("hostlist auth_hosts = %s\n",
 
999
  &no_expand_regex($main{"auth_hosts"}))
 
1000
    if defined $main{"auth_hosts"};
 
1001
printf STDOUT ("hostlist rbl_hosts = %s\n",
 
1002
  &no_expand_regex($main{"rbl_hosts"}))
 
1003
    if defined $main{"rbl_hosts"};
 
1004
printf STDOUT ("hostlist relay_hosts = %s\n",
 
1005
  &no_expand_regex($main{"host_accept_relay"}))
 
1006
    if defined $main{"host_accept_relay"};
 
1007
printf STDOUT ("hostlist auth_relay_hosts = %s\n",
 
1008
  &no_expand_regex($main{"host_auth_accept_relay"}))
 
1009
    if defined $main{"host_auth_accept_relay"};
 
1010
 
 
1011
printf STDOUT ("hostlist auth_over_tls_hosts = %s\n",
 
1012
  &no_expand_regex($main{"auth_over_tls_hosts"}))
 
1013
    if defined $main{"auth_over_tls_hosts"};
 
1014
printf STDOUT ("hostlist tls_hosts = %s\n",
 
1015
  &no_expand_regex($main{"tls_hosts"}))
 
1016
    if defined $main{"tls_hosts"};
 
1017
printf STDOUT ("hostlist tls_relay_hosts = %s\n",
 
1018
  &no_expand_regex($main{"tls_host_accept_relay"}))
 
1019
    if defined $main{"tls_host_accept_relay"};
 
1020
 
 
1021
print STDOUT "\n";
 
1022
 
 
1023
 
 
1024
# Convert various logging options
 
1025
 
 
1026
$log_selector = "";
 
1027
$sep = " \\\n             ";
 
1028
 
 
1029
if (defined $main{"log_level"})
 
1030
  {
 
1031
  my($level) = $main{"log_level"};
 
1032
  $log_selector .= "$sep -retry_defer$sep -skip_delivery" if $level < 5;
 
1033
  $log_selector .= "$sep -lost_incoming_connection$sep -smtp_syntax_error" .
 
1034
                   "$sep -delay_delivery" if $level < 4;
 
1035
  $log_selector .= "$sep -size_reject" if $level < 2;
 
1036
  }
 
1037
 
 
1038
$log_selector .= "$sep -queue_run"
 
1039
  if defined $main{"log_queue_run_level"} &&
 
1040
     defined $main{"log_level"} &&
 
1041
     $main{"log_queue_run_level"} > $main{"log_level"};
 
1042
 
 
1043
$log_selector .= "$sep +address_rewrite"       if &bool("log_rewrites");
 
1044
$log_selector .= "$sep +all_parents"           if &bool("log_all_parents");
 
1045
$log_selector .= "$sep +arguments"             if &bool("log_arguments");
 
1046
$log_selector .= "$sep +incoming_port"         if &bool("log_incoming_port");
 
1047
$log_selector .= "$sep +incoming_interface"    if &bool("log_interface");
 
1048
$log_selector .= "$sep +received_sender"       if &bool("log_received_sender");
 
1049
$log_selector .= "$sep +received_recipients"   if &bool("log_received_recipients");
 
1050
$log_selector .= "$sep +sender_on_delivery"    if &bool("log_sender_on_delivery");
 
1051
$log_selector .= "$sep +smtp_confirmation"     if &bool("log_smtp_confirmation");
 
1052
$log_selector .= "$sep +smtp_connection"       if &bool("log_smtp_connections");
 
1053
$log_selector .= "$sep +smtp_syntax_error"     if &bool("log_smtp_syntax_errors");
 
1054
$log_selector .= "$sep +subject"               if &bool("log_subject");
 
1055
$log_selector .= "$sep +tls_cipher"            if &bool("tls_log_cipher");
 
1056
$log_selector .= "$sep +tls_peerdn"            if &bool("tls_log_peerdn");
 
1057
 
 
1058
 
 
1059
if ($log_selector ne "")
 
1060
  {
 
1061
  print STDOUT "#!!# All previous logging options are combined into a single\n"
 
1062
             . "#!!# option in Exim 4. This setting is an approximation to\n"
 
1063
             . "#!!# the previous state - some logging has changed.\n\n";
 
1064
  print STDOUT "log_selector = $log_selector\n\n";
 
1065
  }
 
1066
 
 
1067
# If deliver_load_max is set, replace it with queue_only_load (taking the
 
1068
# lower value if both set) and also set deliver_queue_load_max if it is
 
1069
# not already set. When scanning for output, deliver_load_max is skipped.
 
1070
 
 
1071
if (defined $main{"deliver_load_max"})
 
1072
  {
 
1073
  &rubric();
 
1074
  print STDERR "\n" .
 
1075
"** deliver_load_max is abolished in Exim 4.\n";
 
1076
 
 
1077
  if (defined $main{"queue_only_load"})
 
1078
    {
 
1079
    $queue_only_load_was_present = 1;
 
1080
    if ($main{"queue_only_load"} < $main{"deliver_load_max"})
 
1081
      {
 
1082
      print STDERR
 
1083
"   As queue_only_load was set lower, deliver_load_max is just removed.\n";
 
1084
      }
 
1085
    else
 
1086
      {
 
1087
      print STDERR
 
1088
"   As queue_only_load was set higher, it's value has been replaced by\n" .
 
1089
"   the value of deliver_load_max.\n";
 
1090
      $main{"queue_only_load"} = $main{"deliver_load_max"};
 
1091
      }
 
1092
    }
 
1093
  else
 
1094
    {
 
1095
    print STDERR
 
1096
"   queue_only_load has been set to the load value.\n";
 
1097
    $main{"queue_only_load"} = $main{"deliver_load_max"};
 
1098
    }
 
1099
 
 
1100
  if (!defined $main{"deliver_queue_load_max"})
 
1101
    {
 
1102
    print STDERR
 
1103
"   deliver_queue_load_max has been set to the value of queue_only_load.\n";
 
1104
    $main{"deliver_queue_load_max"} = $main{"queue_only_load"};
 
1105
    }
 
1106
  else
 
1107
    {
 
1108
    $deliver_queue_load_max_was_present = 1;
 
1109
    }
 
1110
  }
 
1111
 
 
1112
 
 
1113
# Now we scan through the various parts of the file again, making changes
 
1114
# as necessary.
 
1115
 
 
1116
# -------- The main configuration --------
 
1117
 
 
1118
$prefix = "";
 
1119
MainLine: for ($i = 0; $i < $clen; $i++)
 
1120
  {
 
1121
  my($nextline) = "";
 
1122
  $type = &checkline($c[$i]);
 
1123
  last if $type eq "end";
 
1124
 
 
1125
  if ($type eq "macro")
 
1126
    {
 
1127
    $i++ while $c[$i] =~ /\\\s*$|^\s*#/;
 
1128
    next;
 
1129
    }
 
1130
 
 
1131
  if ($type eq "comment") { print STDOUT "$c[$i]\n"; next; }
 
1132
 
 
1133
  # Collect any continuation lines for an option setting
 
1134
 
 
1135
  while ($rest =~ /\\\s*$/s || $nextline =~ /^\s*#/)
 
1136
    {
 
1137
    $nextline = $c[++$i];
 
1138
    $rest .= "\n$nextline";
 
1139
    }
 
1140
 
 
1141
  $rest =~ s/^=\s*//;
 
1142
 
 
1143
  # Deal with main options that are skipped (they are used in other
 
1144
  # options in other places).
 
1145
 
 
1146
  for $skipped (@skipped_options)
 
1147
    {
 
1148
    next MainLine if $name eq $skipped;
 
1149
    }
 
1150
 
 
1151
  # Deal with main options that are totally abolished
 
1152
 
 
1153
  for $abolished (@abolished_options)
 
1154
    {
 
1155
    if ($name eq $abolished)
 
1156
      {
 
1157
      &rubric();
 
1158
      print STDERR "\n" .
 
1159
"** The $name option no longer exists, and has no equivalent\n" .
 
1160
"   in Exim 4.\n";
 
1161
      next MainLine;
 
1162
      }
 
1163
    }
 
1164
 
 
1165
  # There is a special case for rbl_warn_header
 
1166
 
 
1167
  if ($name eq "rbl_warn_header")
 
1168
    {
 
1169
    &rubric();
 
1170
    print STDERR "\n" .
 
1171
"** The $name option no longer exists. In Exim 4 you can achieve the\n" .
 
1172
"   effect by adding a suitable \"message\" statement in the ACL.\n";
 
1173
    }
 
1174
 
 
1175
  # There is a special case for sender_reject and host_reject
 
1176
 
 
1177
  elsif ($name eq "sender_reject" || $name eq "host_reject")
 
1178
    {
 
1179
    &rubric();
 
1180
    print STDERR "\n" .
 
1181
"** The $name option no longer exists. Its data has been used in\n" .
 
1182
"   an Access Control List as if it were in ${name}_recipients.\n";
 
1183
    }
 
1184
 
 
1185
  # And a special message for prohibition_message
 
1186
 
 
1187
  elsif ($name eq "prohibition_message")
 
1188
    {
 
1189
    &rubric();
 
1190
    print STDERR "\n" .
 
1191
"** The prohibition_message option no longer exists. The facility is\n" .
 
1192
"   provided in a different way in Exim 4, via the \"message\" keyword\n" .
 
1193
"   in Access Control Lists. It isn't possible to do an automatic conversion,\n" .
 
1194
"   so the value of prohibition_message has been ignored. You will have to\n" .
 
1195
"   modify the ACLs if you want to reinstate the feature.\n";
 
1196
    }
 
1197
 
 
1198
  # auth_always_advertise gets converted to auth_advertise_hosts
 
1199
 
 
1200
  elsif ($name eq "auth_always_advertise")
 
1201
    {
 
1202
    print STDOUT "#!!# auth_always_advertise converted to auth_advertise_hosts\n";
 
1203
    if (&bool("auth_always_advertise"))
 
1204
      {
 
1205
      print STDOUT "auth_advertise_hosts = *\n";
 
1206
      }
 
1207
    else
 
1208
      {
 
1209
      $sep = "";
 
1210
      print STDOUT "auth_advertise_hosts =";
 
1211
      if (defined $main{"auth_hosts"})
 
1212
        {
 
1213
        print STDOUT "$sep +auth_hosts";
 
1214
        $sep = " :";
 
1215
        }
 
1216
      if (defined $main{"host_accept_relay"})
 
1217
        {
 
1218
        print STDOUT "$sep !+relay_hosts";
 
1219
        $sep = " :";
 
1220
        }
 
1221
      if (defined $main{"host_auth_accept_relay"})
 
1222
        {
 
1223
        print STDOUT "$sep +auth_relay_hosts";
 
1224
        }
 
1225
      print STDOUT "\n";
 
1226
      }
 
1227
    }
 
1228
 
 
1229
  # Deal with main options that have to be rewritten
 
1230
 
 
1231
  elsif ($name eq "accept_timeout")
 
1232
    {
 
1233
    print STDOUT "#!!# accept_timeout renamed receive_timeout\n";
 
1234
    print STDOUT "receive_timeout = $rest\n";
 
1235
    }
 
1236
 
 
1237
  elsif ($name eq "collapse_source_routes")
 
1238
    {
 
1239
    print STDOUT "#!!# collapse_source_routes removed\n";
 
1240
    print STDOUT "#!!# It has been a no-op since 3.10.\n";
 
1241
    }
 
1242
 
 
1243
  elsif ($name eq "daemon_smtp_service")
 
1244
    {
 
1245
    print STDOUT "#!!# daemon_smtp_service renamed daemon_smtp_port\n";
 
1246
    print STDOUT "daemon_smtp_port = $rest\n";
 
1247
    }
 
1248
 
 
1249
  elsif ($name eq "dns_check_names" || $name eq "dns_check_names_pattern")
 
1250
    {
 
1251
    if (!$done_dns_check_names)
 
1252
      {
 
1253
      if (&bool("dns_check_names"))
 
1254
        {
 
1255
        if (defined $main{"dns_check_names_pattern"})
 
1256
          {
 
1257
          &outopt(\%main, "dns_check_names_pattern", 0);
 
1258
          }
 
1259
        }
 
1260
 
 
1261
      else
 
1262
        {
 
1263
        print STDOUT "#!!# dns_check_names has been abolished\n";
 
1264
        print STDOUT "#!!# setting dns_check_pattern empty to turn off check\n";
 
1265
        print STDOUT "dns_check_names_pattern =\n";
 
1266
        }
 
1267
 
 
1268
      $done_dns_check_names = 1;
 
1269
      }
 
1270
    }
 
1271
 
 
1272
  elsif ($name eq "deliver_load_max")
 
1273
    {
 
1274
    print STDOUT "deliver_queue_load_max = $main{'deliver_queue_load_max'}\n"
 
1275
      if !$deliver_queue_load_max_was_present;
 
1276
    print STDOUT "queue_only_load = $main{'queue_only_load'}\n"
 
1277
      if !$queue_only_load_was_present;
 
1278
    }
 
1279
 
 
1280
  elsif ($name eq "errmsg_file")
 
1281
    {
 
1282
    print STDOUT "#!!# errmsg_file renamed bounce_message_file\n";
 
1283
    print STDOUT "bounce_message_file = $rest\n";
 
1284
    }
 
1285
 
 
1286
  elsif ($name eq "errmsg_text")
 
1287
    {
 
1288
    print STDOUT "#!!# errmsg_text renamed bounce_message_text\n";
 
1289
    print STDOUT "bounce_message_text = $rest\n";
 
1290
    }
 
1291
 
 
1292
  elsif ($name eq "forbid_domain_literals")
 
1293
    {
 
1294
    print STDOUT "#!!# forbid_domain_literals replaced by allow_domain_literals\n";
 
1295
    print STDOUT "allow_domain_literals = ",
 
1296
          &bool("forbid_domain_literals")? "false" : "true", "\n";
 
1297
    }
 
1298
 
 
1299
  elsif ($name eq "freeze_tell_mailmaster")
 
1300
    {
 
1301
    print STDOUT "#!!# freeze_tell_mailmaster replaced by freeze_tell\n";
 
1302
    if (&bool("freeze_tell_mailmaster"))
 
1303
      {
 
1304
      print STDOUT "freeze_tell = ",
 
1305
        ((defined $main{"errors_address"})?
 
1306
          $main{"errors_address"} : "postmaster"), "\n";
 
1307
      }
 
1308
    else
 
1309
      {
 
1310
      print STDOUT "#!!# freeze_tell is unset by default\n";
 
1311
      }
 
1312
    }
 
1313
 
 
1314
  elsif ($name eq "helo_verify")
 
1315
    {
 
1316
    print STDOUT "#!!# helo_verify renamed helo_verify_hosts\n";
 
1317
    printf STDOUT ("helo_verify_hosts = %s\n", &no_expand_regex($rest));
 
1318
    }
 
1319
 
 
1320
  elsif ($name eq "ignore_errmsg_errors")
 
1321
    {
 
1322
    print STDOUT "ignore_bounce_errors_after = 0s\n";
 
1323
    }
 
1324
 
 
1325
  elsif ($name eq "ignore_errmsg_errors_after")
 
1326
    {
 
1327
    print STDOUT "#!!# ignore_errmsg_errors_after renamed ignore_bounce_errors_after\n";
 
1328
    print STDOUT "ignore_bounce_errors_after = $rest\n";
 
1329
    }
 
1330
 
 
1331
  elsif ($name eq "ipv4_address_lookup" || $name eq "dns_ipv4_lookup")
 
1332
    {
 
1333
    print STDOUT "#!!# $name changed to dns_ipv4_lookup\n"
 
1334
      if $name eq "ipv4_address_lookup";
 
1335
    print STDOUT "#!!# dns_ipv4_lookup is now a domain list\n";
 
1336
    if (&bool($name))
 
1337
      {
 
1338
      print STDOUT "dns_ipv4_lookup = *\n";
 
1339
      }
 
1340
    else
 
1341
      {
 
1342
      print STDOUT "#!!# default for dns_ipv4_lookup is unset\n";
 
1343
      }
 
1344
    }
 
1345
 
 
1346
  elsif ($name eq "locally_caseless")
 
1347
    {
 
1348
    print STDOUT "#!!# locally_caseless removed\n";
 
1349
    print STDOUT "#!!# caseful_local_part will be added to ex-directors\n";
 
1350
    $add_caseful_local_part = 1;
 
1351
    }
 
1352
 
 
1353
  elsif ($name eq "message_filter_directory2_transport")
 
1354
    {
 
1355
    print STDOUT "#!!# message_filter_directory2_transport removed\n";
 
1356
    }
 
1357
 
 
1358
  elsif ($name =~ /^message_filter(.*)/)
 
1359
    {
 
1360
    print STDOUT "#!!# $name renamed system_filter$1\n";
 
1361
    print STDOUT "system_filter$1 = $rest\n";
 
1362
    }
 
1363
 
 
1364
  elsif ($name eq "queue_remote_domains")
 
1365
    {
 
1366
    print STDOUT "#!!# queue_remote_domains renamed queue_domains\n";
 
1367
    printf STDOUT ("queue_domains = %s\n", &no_expand_regex($rest));
 
1368
    }
 
1369
 
 
1370
  elsif ($name eq "receiver_unqualified_hosts")
 
1371
    {
 
1372
    print STDOUT "#!!# receiver_unqualified_hosts renamed recipient_unqualified_hosts\n";
 
1373
    printf STDOUT ("recipient_unqualified_hosts = %s\n",
 
1374
      &no_expand_regex($rest));
 
1375
    }
 
1376
 
 
1377
  elsif ($name eq "remote_sort")
 
1378
    {
 
1379
    print STDOUT "#!!# remote_sort renamed remote_sort_domains\n";
 
1380
    printf STDOUT ("remote_sort_domains = %s\n", &no_expand_regex($rest));
 
1381
    }
 
1382
 
 
1383
  elsif ($name eq "security")
 
1384
    {
 
1385
    if ($rest eq "unprivileged")
 
1386
      {
 
1387
      print STDOUT "#!!# security=unprivileged changed to deliver_drop_privilege\n";
 
1388
      print STDOUT "deliver_drop_privilege\n";
 
1389
      }
 
1390
    else
 
1391
      {
 
1392
      &rubric();
 
1393
      print STDERR "\n" .
 
1394
"** The 'security' option no longer exists.\n";
 
1395
      }
 
1396
    }
 
1397
 
 
1398
  elsif ($name eq "timestamps_utc")
 
1399
    {
 
1400
    print STDOUT "#!!# timestamps_utc changed to use timezone\n";
 
1401
    print STDOUT "timezone = utc\n";
 
1402
    }
 
1403
 
 
1404
  elsif ($name eq "untrusted_set_sender")
 
1405
    {
 
1406
    print STDOUT "#!!# untrusted_set_sender is now a list of what can be set\n";
 
1407
    print STDOUT "#!!# The default is an empty list.\n";
 
1408
    if (&bool("untrusted_set_sender"))
 
1409
      {
 
1410
      print STDOUT "untrusted_set_sender = *\n";
 
1411
      }
 
1412
    }
 
1413
 
 
1414
  elsif ($name eq "warnmsg_file")
 
1415
    {
 
1416
    print STDOUT "#!!# warnmsg_file renamed warn_message_file\n";
 
1417
    print STDOUT "warn_message_file = $rest\n";
 
1418
    }
 
1419
 
 
1420
  # Remaining options just get copied unless they are one of those that's
 
1421
  # a list where any regular expressions have to be escaped.
 
1422
 
 
1423
  else
 
1424
    {
 
1425
    my($no_expand) = 0;
 
1426
    foreach $o (@list_options)
 
1427
      {
 
1428
      if ($name eq $o)
 
1429
        {
 
1430
        $no_expand = 1;
 
1431
        last;
 
1432
        }
 
1433
      }
 
1434
    &outopt(\%main, $name, $no_expand);
 
1435
    }
 
1436
  }
 
1437
 
 
1438
 
 
1439
# -------- The ACL configuration --------
 
1440
 
 
1441
print STDOUT "\n";
 
1442
print STDOUT "#!!#######################################################!!#\n";
 
1443
print STDOUT "#!!# This new section of the configuration contains ACLs #!!#\n";
 
1444
print STDOUT "#!!# (Access Control Lists) derived from the Exim 3      #!!#\n";
 
1445
print STDOUT "#!!# policy control options.                             #!!#\n";
 
1446
print STDOUT "#!!#######################################################!!#\n";
 
1447
 
 
1448
print STDOUT "\n";
 
1449
print STDOUT "#!!# These ACLs are crudely constructed from Exim 3 options.\n";
 
1450
print STDOUT "#!!# They are almost certainly not optimal. You should study\n";
 
1451
print STDOUT "#!!# them and rewrite as necessary.\n";
 
1452
 
 
1453
print STDOUT "\nbegin acl\n\n";
 
1454
 
 
1455
 
 
1456
# Output an ACL for use after the RCPT command. This combines all the previous
 
1457
# policy checking options.
 
1458
 
 
1459
print STDOUT "#!!# ACL that is used after the RCPT command\n";
 
1460
print STDOUT "check_recipient:\n";
 
1461
 
 
1462
print STDOUT "  # Exim 3 had no checking on -bs messages, so for compatibility\n";
 
1463
print STDOUT "  # we accept if the source is local SMTP (i.e. not over TCP/IP).\n";
 
1464
print STDOUT "  # We do this by testing for an empty sending host field.\n";
 
1465
print STDOUT "  accept  hosts = :\n";
 
1466
 
 
1467
if (defined $main{"tls_verify_ciphers"})
 
1468
  {
 
1469
  print STDOUT "  deny    ";
 
1470
  print STDOUT "hosts = $main{'tls_verify_hosts'}\n         "
 
1471
    if defined $main{"tls_verify_hosts"};
 
1472
  print STDOUT " encrypted = *\n         ";
 
1473
  print STDOUT "!encrypted = $main{'tls_verify_ciphers'}\n";
 
1474
  }
 
1475
 
 
1476
print STDOUT "  deny    hosts = +auth_hosts\n" .
 
1477
             "          message = authentication required\n" .
 
1478
             "         !authenticated = *\n"
 
1479
  if defined $main{"auth_hosts"};
 
1480
 
 
1481
print STDOUT "  deny    hosts = +tls_hosts\n" .
 
1482
             "          message = encryption required\n" .
 
1483
             "         !encrypted = *\n"
 
1484
  if defined $main{"tls_hosts"};
 
1485
 
 
1486
printf STDOUT ("  accept  recipients = %s\n",
 
1487
  &acl_quote(&sort_address_list($main{"recipients_reject_except"},
 
1488
    "recipients_reject_except")))
 
1489
      if defined $main{"recipients_reject_except"};
 
1490
 
 
1491
printf STDOUT ("  accept  senders = %s\n",
 
1492
  &acl_quote(&sort_address_list($main{"recipients_reject_except_senders"},
 
1493
    "recipients_reject_except_senders")))
 
1494
      if defined $main{"recipients_reject_except_senders"};
 
1495
 
 
1496
printf STDOUT ("  deny    hosts = %s\n", &acl_quote($main{"host_reject"}))
 
1497
  if defined $main{"host_reject"};
 
1498
 
 
1499
printf STDOUT ("  deny    hosts = %s\n",
 
1500
  &acl_quote($main{"host_reject_recipients"}))
 
1501
    if defined $main{"host_reject_recipients"};
 
1502
 
 
1503
if (defined $main{"rbl_domains"})
 
1504
  {
 
1505
  my($msg) = "message = host is listed in \$dnslist_domain\n          ";
 
1506
  my($hlist) = (defined $main{"rbl_hosts"})?
 
1507
    "hosts = +rbl_hosts\n          " : "";
 
1508
 
 
1509
  print STDOUT "  accept  ${hlist}dnslists = $rbl_accept_domains\n"
 
1510
    if defined $rbl_accept_domains;
 
1511
  print STDOUT "  deny    ${hlist}${msg}dnslists = $rbl_reject_domains\n"
 
1512
    if defined $rbl_reject_domains;
 
1513
  print STDOUT "  warn    ${hlist}" .
 
1514
    "message = X-Warning: \$sender_host_address is listed at \$dnslist_domain\n" .
 
1515
    "          dnslists = $rbl_warn_domains\n"
 
1516
      if defined $rbl_warn_domains;
 
1517
 
 
1518
  if (defined $main{"host_accept_relay"})
 
1519
    {
 
1520
    $hlist .= "hosts = !+relay_hosts\n          ";
 
1521
    print STDOUT "  accept  ${hlist}dnslists = $rbl_accept_skiprelay\n"
 
1522
      if defined $rbl_accept_skiprelay;
 
1523
    print STDOUT "  deny    ${hlist}${msg}dnslists = $rbl_reject_skiprelay\n"
 
1524
      if defined $rbl_reject_skiprelay;
 
1525
    print STDOUT "  warn    ${hlist}" .
 
1526
      "message = X-Warning: \$sender_host_address is listed at \$dnslist_domain\n" .
 
1527
      "          dnslists = $rbl_warn_skiprelay\n"
 
1528
        if defined $rbl_warn_skiprelay;
 
1529
    }
 
1530
  }
 
1531
 
 
1532
printf STDOUT ("  deny    senders = %s\n",
 
1533
  &acl_quote(&sort_address_list($main{"sender_reject"}, "sender_reject")))
 
1534
    if defined $main{"sender_reject"};
 
1535
 
 
1536
printf STDOUT ("  deny    senders = %s\n",
 
1537
  &acl_quote(&sort_address_list($main{"sender_reject_recipients"},
 
1538
    "sender_reject_recipients")))
 
1539
      if defined $main{"sender_reject_recipients"};
 
1540
 
 
1541
if (&bool("sender_verify"))
 
1542
  {
 
1543
  if (defined $main{"sender_verify_hosts_callback"} &&
 
1544
      defined $main{"sender_verify_callback_domains"})
 
1545
    {
 
1546
    printf STDOUT ("  deny    hosts = %s\n",
 
1547
      &acl_quote($main{"sender_verify_hosts_callback"}));
 
1548
    printf STDOUT ("          sender_domains = %s\n",
 
1549
      &acl_quote($main{"sender_verify_callback_domains"}));
 
1550
    print  STDOUT  "         !verify = sender/callout";
 
1551
    print  STDOUT  "=$main{\"sender_verify_callback_timeout\"}"
 
1552
      if defined $main{"sender_verify_callback_timeout"};
 
1553
    print  STDOUT  "\n";
 
1554
    }
 
1555
 
 
1556
  if (defined $main{"sender_verify_hosts"})
 
1557
    {
 
1558
    printf STDOUT ("  deny    hosts = %s\n",
 
1559
      &acl_quote($main{"sender_verify_hosts"}));
 
1560
    print  STDOUT  "         !verify = sender\n";
 
1561
    }
 
1562
  else
 
1563
    {
 
1564
    print STDOUT "  require verify = sender\n";
 
1565
    }
 
1566
  }
 
1567
 
 
1568
if (&bool("receiver_verify"))
 
1569
  {
 
1570
  print  STDOUT  "  deny    message = unrouteable address\n";
 
1571
  printf STDOUT ("          recipients = %s\n",
 
1572
    &acl_quote(&sort_address_list($main{"receiver_verify_addresses"},
 
1573
      "receiver_verify_addresses")))
 
1574
        if defined $main{"receiver_verify_addresses"};
 
1575
  printf STDOUT ("          hosts = %s\n",
 
1576
    &acl_quote($main{"receiver_verify_hosts"}))
 
1577
      if defined $main{"receiver_verify_hosts"};
 
1578
  printf STDOUT ("          senders = %s\n",
 
1579
    &acl_quote(&sort_address_list($main{"receiver_verify_senders"},
 
1580
      "receiver_verify_senders")))
 
1581
        if defined $main{"receiver_verify_senders"};
 
1582
  print  STDOUT  "         !verify = recipient\n";
 
1583
  }
 
1584
 
 
1585
print STDOUT "  accept  domains = +local_domains\n"
 
1586
  if $local_domains !~ /^\s*$/;
 
1587
 
 
1588
print STDOUT "  accept  domains = +relay_domains\n"
 
1589
  if $relay_domains !~ /^\s*$/;
 
1590
 
 
1591
if (defined $main{"host_accept_relay"})
 
1592
  {
 
1593
  if (defined $main{"sender_address_relay"})
 
1594
    {
 
1595
    if (defined $main{"sender_address_relay_hosts"})
 
1596
      {
 
1597
      printf STDOUT ("  accept  hosts = %s\n",
 
1598
        &acl_quote($main{"sender_address_relay_hosts"}));
 
1599
      print  STDOUT  "          endpass\n";
 
1600
      print  STDOUT  "          message = invalid sender\n";
 
1601
      printf STDOUT ("          senders = %s\n",
 
1602
        &acl_quote(&sort_address_list($main{"sender_address_relay"},
 
1603
          "sender_address_relay")));
 
1604
      print  STDOUT  "  accept  hosts = +relay_hosts\n";
 
1605
      }
 
1606
    else
 
1607
      {
 
1608
      print  STDOUT  "  accept  hosts = +relay_hosts\n";
 
1609
      print  STDOUT  "          endpass\n";
 
1610
      print  STDOUT  "          message = invalid sender\n";
 
1611
      printf STDOUT ("          senders = %s\n",
 
1612
        &acl_quote(&sort_address_list($main{"sender_address_relay"},
 
1613
          "sender_address_relay")));
 
1614
      }
 
1615
    }
 
1616
  else
 
1617
    {
 
1618
    print STDOUT "  accept  hosts = +relay_hosts\n";
 
1619
    }
 
1620
  }
 
1621
 
 
1622
print STDOUT "  accept  hosts = +auth_relay_hosts\n" .
 
1623
             "          endpass\n" .
 
1624
             "          message = authentication required\n" .
 
1625
             "          authenticated = *\n"
 
1626
  if defined $main{"host_auth_accept_relay"};
 
1627
 
 
1628
print STDOUT "  accept  hosts = +tls_relay_hosts\n" .
 
1629
             "          endpass\n" .
 
1630
             "          message = encryption required\n" .
 
1631
             "          encrypted = *\n"
 
1632
  if defined $main{"tls_host_accept_relay"};
 
1633
 
 
1634
print STDOUT "  deny    message = relay not permitted\n\n";
 
1635
 
 
1636
 
 
1637
# Output an ACL for use after the DATA command. This is concerned with
 
1638
# header checking.
 
1639
 
 
1640
print STDOUT "#!!# ACL that is used after the DATA command\n";
 
1641
print STDOUT "check_message:\n";
 
1642
 
 
1643
# Default for headers_checks_fail is true
 
1644
 
 
1645
if (!defined $main{"headers_checks_fail"} ||
 
1646
    $main{"headers_checks_fail"} eq "true")
 
1647
  {
 
1648
  print STDOUT "  require verify = header_syntax\n"
 
1649
    if &bool("headers_check_syntax");
 
1650
  print STDOUT "  require verify = header_sender\n"
 
1651
    if &bool("headers_sender_verify");
 
1652
  print STDOUT "  accept  senders = !:\n  require verify = header_sender\n"
 
1653
    if &bool("headers_sender_verify_errmsg");
 
1654
  }
 
1655
else
 
1656
  {
 
1657
  print STDOUT "  warn    !verify = header_syntax\n"
 
1658
    if &bool("headers_check_syntax");
 
1659
  print STDOUT "  warn    !verify = header_sender\n"
 
1660
    if &bool("headers_sender_verify");
 
1661
  print STDOUT "  accept  senders = !:\n  warn    !verify = header_sender\n"
 
1662
    if &bool("headers_sender_verify_errmsg");
 
1663
  }
 
1664
 
 
1665
print STDOUT "  accept\n\n";
 
1666
 
 
1667
 
 
1668
# Output an ACL for AUTH if required
 
1669
 
 
1670
if (defined $main{"auth_over_tls_hosts"})
 
1671
  {
 
1672
  print STDOUT "#!!# ACL that is used after the AUTH command\n" .
 
1673
               "check_auth:\n" .
 
1674
               "  accept  hosts = +auth_over_tls_hosts\n" .
 
1675
               "          endpass\n" .
 
1676
               "          message = STARTTLS required before AUTH\n" .
 
1677
               "          encrypted = *\n" .
 
1678
               "  accept\n";
 
1679
  }
 
1680
 
 
1681
 
 
1682
# Output ACLs for ETRN, EXPN, and VRFY if required
 
1683
 
 
1684
if (defined $main{"smtp_etrn_hosts"})
 
1685
  {
 
1686
  print STDOUT "#!!# ACL that is used after the ETRN command\n" .
 
1687
               "check_etrn:\n";
 
1688
  print STDOUT "  deny    hosts = +auth_hosts\n" .
 
1689
               "          message = authentication required\n" .
 
1690
               "         !authenticated = *\n"
 
1691
    if defined $main{"auth_hosts"};
 
1692
  print STDOUT "  accept  hosts = $main{\"smtp_etrn_hosts\"}\n\n";
 
1693
  }
 
1694
 
 
1695
if (defined $main{"smtp_expn_hosts"})
 
1696
  {
 
1697
  print STDOUT "#!!# ACL that is used after the EXPN command\n" .
 
1698
               "check_expn:\n";
 
1699
  print STDOUT "  deny    hosts = +auth_hosts\n" .
 
1700
               "          message = authentication required\n" .
 
1701
               "         !authenticated = *\n"
 
1702
    if defined $main{"auth_hosts"};
 
1703
  print STDOUT "  accept  hosts = $main{\"smtp_expn_hosts\"}\n\n";
 
1704
  }
 
1705
 
 
1706
if (&bool("smtp_verify"))
 
1707
  {
 
1708
  print STDOUT "#!!# ACL that is used after the VRFY command\n" .
 
1709
               "check_vrfy:\n";
 
1710
  print STDOUT "  deny    hosts = +auth_hosts\n" .
 
1711
               "          message = authentication required\n" .
 
1712
               "         !authenticated = *\n"
 
1713
    if defined $main{"auth_hosts"};
 
1714
  print STDOUT "  accept\n\n";
 
1715
  }
 
1716
 
 
1717
# -------- The authenticators --------
 
1718
 
 
1719
$started = 0;
 
1720
for ($i = $auth_start; $i < $clen; $i++)
 
1721
  {
 
1722
  if (!$started)
 
1723
    {
 
1724
    if ($c[$i] !~ /^\s*(#|$)/)
 
1725
      {
 
1726
      print STDOUT "\nbegin authenticators\n\n";
 
1727
      $started = 1;
 
1728
      }
 
1729
    }
 
1730
  print STDOUT "$c[$i]\n";
 
1731
  }
 
1732
 
 
1733
 
 
1734
# -------- Rewrite section --------
 
1735
 
 
1736
$started = 0;
 
1737
for ($i = $rewrite_start; $i < $clen && $i < $auth_start - 1; $i++)
 
1738
  {
 
1739
  if (!$started)
 
1740
    {
 
1741
    if ($c[$i] !~ /^\s*(#|$)/)
 
1742
      {
 
1743
      print STDOUT "\nbegin rewrite\n\n";
 
1744
      $started = 1;
 
1745
      }
 
1746
    }
 
1747
  &print_no_expand($c[$i]);
 
1748
  }
 
1749
 
 
1750
 
 
1751
# -------- The routers configuration --------
 
1752
 
 
1753
# The new routers configuration is created out of the old directors and routers
 
1754
# configuration. We put the old routers first, adding a "domains" option to
 
1755
# any that don't have one, to make them select the domains that do not match
 
1756
# the original local_domains. The routers get modified as necessary, and the
 
1757
# final one has "no_more" set, unless it has conditions. In that case we have
 
1758
# to add an extra router to be sure of failing all non-local addresses that
 
1759
# fall through. We do this also if there are no routers at all. The old
 
1760
# directors follow, modified as required.
 
1761
 
 
1762
$prefix = "r.";
 
1763
undef @comments;
 
1764
 
 
1765
print STDOUT "\n";
 
1766
print STDOUT "#!!#######################################################!!#\n";
 
1767
print STDOUT "#!!# Here follow routers created from the old routers,   #!!#\n";
 
1768
print STDOUT "#!!# for handling non-local domains.                     #!!#\n";
 
1769
print STDOUT "#!!#######################################################!!#\n";
 
1770
 
 
1771
print STDOUT "\nbegin routers\n\n";
 
1772
 
 
1773
for ($i = $router_start; $i < $clen; $i++)
 
1774
  {
 
1775
  $type = &checkline($c[$i]);
 
1776
  last if $type eq "end";
 
1777
 
 
1778
  if ($type eq "comment") { push(@comments, "$c[$i]\n"); next; }
 
1779
 
 
1780
  # When we hit the start of a driver, modify its options as necessary,
 
1781
  # and then output it from the stored option settings, having first output
 
1782
  # and previous comments.
 
1783
 
 
1784
  if ($type eq "driver")
 
1785
    {
 
1786
    print STDOUT shift @comments while scalar(@comments) > 0;
 
1787
 
 
1788
    $hash = $driverlist{"$prefix$name"};
 
1789
    $driver = $$hash{"driver"};
 
1790
    print STDOUT "$name:\n";
 
1791
 
 
1792
    $add_no_more =
 
1793
      ! defined $$hash{"domains"} &&
 
1794
      ! defined $$hash{"local_parts"} &&
 
1795
      ! defined $$hash{"senders"} &&
 
1796
      ! defined $$hash{"condition"} &&
 
1797
      ! defined $$hash{"require_files"} &&
 
1798
      (!defined $$hash{"verify_only"} || $$hash{"verify_only"} eq "false") &&
 
1799
      (!defined $$hash{"verify"} || $$hash{"verify"} eq "true");
 
1800
 
 
1801
    # Create a "domains" setting if there isn't one, unless local domains
 
1802
    # was explicitly empty.
 
1803
 
 
1804
    $$hash{"domains"} = "! +local_domains"
 
1805
      if !defined $$hash{"domains"} && $local_domains !~ /^\s*$/;
 
1806
 
 
1807
    # If the router had a local_parts setting, add caseful_local_part
 
1808
 
 
1809
    $$hash{"caseful_local_part"} = "true" if defined $$hash{"local_parts"};
 
1810
 
 
1811
    # If the router has "self=local" set, change it to "self=pass", and
 
1812
    # set pass_router to the router that was the first director. Change the
 
1813
    # obsolete self settings of "fail_hard" and "fail_soft" to "fail" and
 
1814
    # "pass".
 
1815
 
 
1816
    if (defined $$hash{"self"})
 
1817
      {
 
1818
      if ($$hash{"self"} eq "local")
 
1819
        {
 
1820
        $$hash{"self"} = "pass";
 
1821
        $$hash{"pass_router"} = $first_director;
 
1822
        }
 
1823
      elsif ($$hash{"self"} eq "fail_hard")
 
1824
        {
 
1825
        $$hash{"self"} = "fail";
 
1826
        }
 
1827
      elsif ($$hash{"self"} eq "fail_soft")
 
1828
        {
 
1829
        $$hash{"self"} = "pass";
 
1830
        }
 
1831
      }
 
1832
 
 
1833
    # If the router had a require_files setting, check it for user names
 
1834
    # and colons that are part of expansion items
 
1835
 
 
1836
    if (defined $$hash{"require_files"})
 
1837
      {
 
1838
      &check_require($$hash{"require_files"}, "'$name' router");
 
1839
      if (($$hash{"require_files"} =~ s/(\$\{\w+):/$1::/g) > 0 ||
 
1840
          ($$hash{"require_files"} =~ s/ldap:/ldap::/g) > 0)
 
1841
        {
 
1842
        &rubric();
 
1843
        print STDERR "\n" .
 
1844
"*** A setting of require_files in the $name router contains\n" .
 
1845
"    a colon in what appears to be an expansion item. In Exim 3, the\n" .
 
1846
"    whole string was expanded before splitting the list, but in Exim 4\n" .
 
1847
"    each item is expanded separately, so colons that are not list\n" .
 
1848
"    item separators have to be doubled. One or more such colons in this\n" .
 
1849
"    list have been doubled as a precaution. Please check the result.\n";
 
1850
        }
 
1851
      }
 
1852
 
 
1853
    # If the router had a "senders" setting, munge the address list
 
1854
 
 
1855
    $$hash{"senders"} = &sort_address_list($$hash{"senders"}, "senders")
 
1856
      if defined $$hash{"senders"};
 
1857
 
 
1858
    # ---- Changes to domainlist router ----
 
1859
 
 
1860
    if ($driver eq "domainlist")
 
1861
      {
 
1862
      &abolished($hash, "A domainlist router",
 
1863
        "modemask", "owners", "owngroups",
 
1864
        "qualify_single", "search_parents");
 
1865
 
 
1866
      # The name has changed
 
1867
 
 
1868
      $$hash{"driver"} = "manualroute";
 
1869
 
 
1870
      # Turn "route_file", "route_query" and "route_queries" into lookups for
 
1871
      # route_data.
 
1872
 
 
1873
      if (defined $$hash{"route_file"})
 
1874
        {
 
1875
        $$hash{"route_data"} = "\${lookup\{\$domain\}$$hash{'search_type'}" .
 
1876
                         "\{$$hash{'route_file'}\}\}";
 
1877
        }
 
1878
      elsif (defined $$hash{"route_query"})
 
1879
        {
 
1880
        $$hash{"route_data"} = "\${lookup $$hash{'search_type'}" .
 
1881
                               "\{" . &unquote($$hash{'route_query'}) . "\}\}";
 
1882
        }
 
1883
      elsif (defined $$hash{"route_queries"})
 
1884
        {
 
1885
        $endkets = 0;
 
1886
        $$hash{"route_data"} = "";
 
1887
        $route_queries = $$hash{'route_queries'};
 
1888
        $route_queries =~ s/^"(.*)"$/$1/s;
 
1889
        $route_queries =~ s/::/++colons++/g;
 
1890
        @qq = split(/:/, $route_queries);
 
1891
 
 
1892
        foreach $q (@qq)
 
1893
          {
 
1894
          $q =~ s/\+\+colons\+\+/:/g;
 
1895
          $q =~ s/^\s+//;
 
1896
          $q =~ s/\s+$//;
 
1897
          if ($endkets > 0)
 
1898
            {
 
1899
            $$hash{"route_data"} .= "\\\n    {";
 
1900
            $endkets++;
 
1901
            }
 
1902
          $$hash{"route_data"} .= "\${lookup $$hash{'search_type'} \{$q\}\{\$value\}";
 
1903
          $endkets++;
 
1904
          }
 
1905
 
 
1906
        $$hash{"route_data"} .= "}" x $endkets;
 
1907
        }
 
1908
 
 
1909
      delete $$hash{"route_file"};
 
1910
      delete $$hash{"route_query"};
 
1911
      delete $$hash{"route_queries"};
 
1912
      delete $$hash{"search_type"};
 
1913
 
 
1914
      # But we can't allow both route_data and route_list
 
1915
 
 
1916
      if (defined $$hash{"route_data"} && defined $$hash{"route_list"})
 
1917
        {
 
1918
        &rubric();
 
1919
        print STDERR "\n" .
 
1920
"** An Exim 3 'domainlist' router called '$name' contained a 'route_list'\n" .
 
1921
"   option as well as a setting of 'route_file', 'route_query', or\n" .
 
1922
"   'route_queries'. The latter has been turned into a 'route_data' setting,\n".
 
1923
"   but in Exim 4 you can't have both 'route_data' and 'route_list'. You'll\n" .
 
1924
"   have to rewrite this router; in the meantime, 'route_list' has been\n" .
 
1925
"   omitted.\n";
 
1926
        print STDOUT "#!!# route_list option removed\n";
 
1927
        delete $$hash{"route_list"};
 
1928
        }
 
1929
 
 
1930
      # Change bydns_a into bydns in a route_list; also bydns_mx, but that
 
1931
      # works differently.
 
1932
 
 
1933
      if (defined $$hash{"route_list"})
 
1934
        {
 
1935
        $$hash{"route_list"} =~ s/bydns_a/bydns/g;
 
1936
        if ($$hash{"route_list"} =~ /bydns_mx/)
 
1937
          {
 
1938
          $$hash{"route_list"} =~ s/bydns_mx/bydns/g;
 
1939
          &rubric();
 
1940
          print STDERR "\n" .
 
1941
"*** An Exim 3 'domainlist' router called '$name' contained a 'route_list'\n" .
 
1942
"    option which used 'bydns_mx'. This feature no longer exists in Exim 4.\n" .
 
1943
"    It has been changed to 'bydns', but it won't have the same effect,\n" .
 
1944
"    because it will look for A rather than MX records. Use the 'dnslookup'\n" .
 
1945
"    router to do MX lookups - if you want to override the hosts found from\n" .
 
1946
"    MX records, you should route to a special 'smtp' transport which has\n" .
 
1947
"    both 'hosts' and 'hosts_override' set.\n";
 
1948
          }
 
1949
        }
 
1950
 
 
1951
      # Arrange to not expand regex
 
1952
 
 
1953
      $$hash{"route_list"} = &no_expand_regex($$hash{"route_list"}, ";")
 
1954
        if (defined $$hash{"route_list"})
 
1955
      }
 
1956
 
 
1957
 
 
1958
    # ---- Changes to iplookup router ----
 
1959
 
 
1960
    elsif ($driver eq "iplookup")
 
1961
      {
 
1962
      &renamed($hash, "service", "port");
 
1963
      }
 
1964
 
 
1965
 
 
1966
    # ---- Changes to lookuphost router ----
 
1967
 
 
1968
    elsif ($driver eq "lookuphost")
 
1969
      {
 
1970
      $$hash{"driver"} = "dnslookup";
 
1971
 
 
1972
      if (defined $$hash{"gethostbyname"})
 
1973
        {
 
1974
        &rubric();
 
1975
        print STDERR "\n" .
 
1976
"** An Exim 3 'lookuphost' router called '$name' used the 'gethostbyname'\n" .
 
1977
"   option, which no longer exists. You will have to rewrite it.\n";
 
1978
        print STDOUT "#!!# gethostbyname option removed\n";
 
1979
        delete $$hash{"gethostbyname"};
 
1980
        }
 
1981
 
 
1982
      $$hash{"mx_domains"} = &no_expand_regex($$hash{"mx_domains"})
 
1983
        if defined $$hash{"mx_domains"};
 
1984
      }
 
1985
 
 
1986
 
 
1987
    # ---- Changes to the queryprogram router ----
 
1988
 
 
1989
    elsif ($driver eq "queryprogram")
 
1990
      {
 
1991
      &rubric();
 
1992
      print STDERR "\n" .
 
1993
"** The configuration contains a 'queryprogram' router. Please note that\n" .
 
1994
"   the specification for the text that is returned by the program run\n" .
 
1995
"   by this router has changed in Exim 4. You will need to modify your\n" .
 
1996
"   program.\n";
 
1997
 
 
1998
      if (!defined $$hash{'command_user'})
 
1999
        {
 
2000
        &rubric();
 
2001
        print STDERR "\n" .
 
2002
"** The 'queryprogram' router called '$name' does not have a setting for\n" .
 
2003
"   the 'command_user' option. This is mandatory in Exim 4. A setting of\n" .
 
2004
"   'nobody' has been created.\n";
 
2005
        $$hash{"command_user"} = "nobody";
 
2006
        }
 
2007
      }
 
2008
 
 
2009
 
 
2010
    # -------------------------------------
 
2011
 
 
2012
    # Output the router's option settings
 
2013
 
 
2014
    &outdriver($hash);
 
2015
    next;
 
2016
    }
 
2017
 
 
2018
  # Skip past any continuation lines for an option setting
 
2019
  while ($c[$i] =~ /\\\s*$/s && $i < $clen - 1)
 
2020
    {
 
2021
    $i++;
 
2022
    $i++ while ($c[$i] =~ /^\s*#/);
 
2023
    }
 
2024
  }
 
2025
 
 
2026
# Add "no_more" to the final driver from the old routers, provided it had no
 
2027
# conditions. Otherwise, or if there were no routers, make up one to fail all
 
2028
# non-local domains.
 
2029
 
 
2030
if ($add_no_more)
 
2031
  {
 
2032
  print STDOUT "  no_more\n";
 
2033
  print STDOUT shift @comments while scalar(@comments) > 0;
 
2034
  }
 
2035
else
 
2036
  {
 
2037
  print STDOUT shift @comments while scalar(@comments) > 0;
 
2038
  print STDOUT "\n#!!# This new router is put here to fail all domains that\n";
 
2039
  print STDOUT "#!!# were not in local_domains in the Exim 3 configuration.\n\n";
 
2040
  print STDOUT "fail_remote_domains:\n";
 
2041
  print STDOUT "  driver = redirect\n";
 
2042
  print STDOUT "  domains = ! +local_domains\n";
 
2043
  print STDOUT "  allow_fail\n";
 
2044
  print STDOUT "  data = :fail: unrouteable mail domain \"\$domain\"\n\n";
 
2045
  }
 
2046
 
 
2047
# Now copy the directors, making appropriate changes
 
2048
 
 
2049
print STDOUT "\n";
 
2050
print STDOUT "#!!#######################################################!!#\n";
 
2051
print STDOUT "#!!# Here follow routers created from the old directors, #!!#\n";
 
2052
print STDOUT "#!!# for handling local domains.                         #!!#\n";
 
2053
print STDOUT "#!!#######################################################!!#\n";
 
2054
 
 
2055
$prefix = "d.";
 
2056
for ($i = $director_start; $i < $clen; $i++)
 
2057
  {
 
2058
  $type = &checkline($c[$i]);
 
2059
  last if $type eq "end";
 
2060
 
 
2061
  if ($type eq "comment") { print STDOUT "$c[$i]\n"; next; }
 
2062
 
 
2063
  undef $second_router;
 
2064
 
 
2065
  if ($type eq "driver")
 
2066
    {
 
2067
    $hash = $driverlist{"$prefix$name"};
 
2068
    $driver = $$hash{"driver"};
 
2069
    print STDOUT "$name:\n";
 
2070
 
 
2071
    $$hash{"caseful_local_part"} = "true" if $add_caseful_local_part;
 
2072
 
 
2073
    if (defined $$hash{"local_parts"} &&
 
2074
        (defined $$hash{"prefix"} || defined $hash{"suffix"}))
 
2075
      {
 
2076
      &rubric();
 
2077
      print STDERR "\n" .
 
2078
"** The Exim 3 configuration contains a director called '$name' which has\n" .
 
2079
"   'local_parts' set, together with either or both of 'prefix' and 'suffix'\n".
 
2080
"   This combination has a different effect in Exim 4, where the affix\n" .
 
2081
"   is removed *before* 'local_parts' is tested. You will probably need\n" .
 
2082
"   to make changes to this driver.\n";
 
2083
      }
 
2084
 
 
2085
    &renamed($hash, "prefix", "local_part_prefix");
 
2086
    &renamed($hash, "prefix_optional", "local_part_prefix_optional");
 
2087
    &renamed($hash, "suffix", "local_part_suffix");
 
2088
    &renamed($hash, "suffix_optional", "local_part_suffix_optional");
 
2089
    &renamed($hash, "new_director", "redirect_router");
 
2090
 
 
2091
    &handle_current_and_home_directory($hash, $driver, $name);
 
2092
 
 
2093
    # If the director had a require_files setting, check it for user names
 
2094
    # and colons that are part of expansion items
 
2095
 
 
2096
    if (defined $$hash{"require_files"})
 
2097
      {
 
2098
      &check_require($$hash{"require_files"}, "'$name' director");
 
2099
      if (($$hash{"require_files"} =~ s/(\$\{\w+):/$1::/g) > 0 ||
 
2100
          ($$hash{"require_files"} =~ s/ldap:/ldap::/g) > 0)
 
2101
        {
 
2102
        &rubric();
 
2103
        print STDERR "\n" .
 
2104
"*** A setting of require_files in the $name director contains\n" .
 
2105
"    a colon in what appears to be an expansion item. In Exim 3, the\n" .
 
2106
"    whole string was expanded before splitting the list, but in Exim 4\n" .
 
2107
"    each item is expanded separately, so colons that are not list\n" .
 
2108
"    item separators have to be doubled. One or more such colons in this\n" .
 
2109
"    list have been doubled as a precaution. Please check the result.\n";
 
2110
        }
 
2111
      }
 
2112
 
 
2113
    # If the director had a "senders" setting, munge the address list
 
2114
 
 
2115
    $$hash{"senders"} = &sort_address_list($$hash{"senders"}, "senders")
 
2116
      if defined $$hash{"senders"};
 
2117
 
 
2118
    # ---- Changes to aliasfile director ----
 
2119
 
 
2120
    if ($driver eq "aliasfile")
 
2121
      {
 
2122
      &abolished($hash, "An aliasfile director",
 
2123
        "directory2_transport", "freeze_missing_include",
 
2124
        "modemask", "owners", "owngroups");
 
2125
 
 
2126
      $$hash{"driver"} = "redirect";
 
2127
 
 
2128
      $key = "\$local_part";
 
2129
      $key = "\$local_part\@\$domain"
 
2130
        if defined $$hash{"include_domain"} &&
 
2131
          $$hash{"include_domain"} eq "true";
 
2132
      delete $$hash{"include_domain"};
 
2133
 
 
2134
      if (defined $$hash{"forbid_special"} && $$hash{"forbid_special"} eq "true")
 
2135
        {
 
2136
        $$hash{"forbid_blackhole"} = "true";
 
2137
        }
 
2138
      else
 
2139
        {
 
2140
        $$hash{"allow_defer"} = "true";
 
2141
        $$hash{"allow_fail"} = "true";
 
2142
        }
 
2143
      delete $$hash{"forbid_special"};
 
2144
 
 
2145
      # Deal with "file", "query", or "queries"
 
2146
 
 
2147
      if (defined $$hash{"file"})
 
2148
        {
 
2149
        $$hash{"data"} =
 
2150
          "\$\{lookup\{$key\}$$hash{'search_type'}\{$$hash{'file'}\}\}";
 
2151
        if (defined $$hash{"optional"} && $$hash{"optional"} eq "true")
 
2152
          {
 
2153
          $$hash{"data"} =
 
2154
            "\$\{if exists\{$$hash{'file'}\}\{$$hash{'data'}\}\}";
 
2155
          }
 
2156
        delete $$hash{"optional"};
 
2157
        }
 
2158
      elsif (defined $$hash{"query"})
 
2159
        {
 
2160
        &abolished($hash, "An aliasfile director", "optional");
 
2161
        $$hash{"data"} = "\${lookup $$hash{'search_type'} " .
 
2162
                         "\{" . &unquote($$hash{'query'}) . "\}\}";
 
2163
        }
 
2164
      else   # Must be queries
 
2165
        {
 
2166
        &abolished($hash, "An aliasfile director", "optional");
 
2167
        $endkets = 0;
 
2168
        $$hash{"data"} = "";
 
2169
        $queries = $$hash{'queries'};
 
2170
        $queries =~ s/^"(.*)"$/$1/s;
 
2171
        $queries =~ s/::/++colons++/g;
 
2172
        @qq = split(/:/, $queries);
 
2173
 
 
2174
        foreach $q (@qq)
 
2175
          {
 
2176
          $q =~ s/\+\+colons\+\+/:/g;
 
2177
          $q =~ s/^\s+//;
 
2178
          $q =~ s/\s+$//;
 
2179
          if ($endkets > 0)
 
2180
            {
 
2181
            $$hash{"data"} .= "\\\n    {";
 
2182
            $endkets++;
 
2183
            }
 
2184
          $$hash{"data"} .= "\${lookup $$hash{'search_type'} \{$q\}\{\$value\}";
 
2185
          $endkets++;
 
2186
          }
 
2187
 
 
2188
        $$hash{"data"} .= "}" x $endkets;
 
2189
        }
 
2190
 
 
2191
      $$hash{"data"} = "\${expand:$$hash{'data'}\}"
 
2192
        if (defined $$hash{"expand"} && $$hash{"expand"} eq "true");
 
2193
 
 
2194
      delete $$hash{"expand"};
 
2195
      delete $$hash{"file"};
 
2196
      delete $$hash{"query"};
 
2197
      delete $$hash{"queries"};
 
2198
      delete $$hash{"search_type"};
 
2199
 
 
2200
      # Turn aliasfile + transport into accept + condition
 
2201
 
 
2202
      if (defined $$hash{'transport'})
 
2203
        {
 
2204
        &rubric();
 
2205
        if (!defined $$hash{'condition'})
 
2206
          {
 
2207
          print STDERR "\n" .
 
2208
"** The Exim 3 configuration contains an aliasfile director called '$name',\n".
 
2209
"   which has 'transport' set. This has been turned into an 'accept' router\n".
 
2210
"   with a 'condition' setting, but should be carefully checked.\n";
 
2211
          $$hash{'driver'} = "accept";
 
2212
          $$hash{'condition'} =
 
2213
            "\$\{if eq \{\}\{$$hash{'data'}\}\{no\}\{yes\}\}";
 
2214
          delete $$hash{'data'};
 
2215
          delete $$hash{'allow_defer'};
 
2216
          delete $$hash{'allow_fail'};
 
2217
          }
 
2218
        else
 
2219
          {
 
2220
          print STDERR "\n" .
 
2221
"** The Exim 3 configuration contains an aliasfile director called '$name',\n".
 
2222
"   which has 'transport' set. This cannot be turned into an 'accept' router\n".
 
2223
"   with a 'condition' setting, because there is already a 'condition'\n" .
 
2224
"   setting. It has been left as 'redirect' with a transport, which is\n" .
 
2225
"   invalid - you must sort this one out.\n";
 
2226
          }
 
2227
        }
 
2228
      }
 
2229
 
 
2230
 
 
2231
    # ---- Changes to forwardfile director ----
 
2232
 
 
2233
    elsif ($driver eq "forwardfile")
 
2234
      {
 
2235
      &abolished($hash, "A forwardfile director",
 
2236
        "check_group", "directory2_transport",
 
2237
        "freeze_missing_include", "match_directory",
 
2238
        "seteuid");
 
2239
 
 
2240
      &renamed($hash, "filter", "allow_filter");
 
2241
 
 
2242
      $$hash{"driver"} = "redirect";
 
2243
      $$hash{"check_local_user"} = "true"
 
2244
        if !defined $$hash{"check_local_user"};
 
2245
 
 
2246
      if (defined $$hash{"forbid_pipe"} && $$hash{"forbid_pipe"} eq "true")
 
2247
        {
 
2248
        print STDOUT "#!!# forbid_filter_run added because forbid_pipe is set\n";
 
2249
        $$hash{"forbid_filter_run"} = "true";
 
2250
        }
 
2251
 
 
2252
      if (defined $$hash{'allow_system_actions'} &&
 
2253
          $$hash{'allow_system_actions'} eq 'true')
 
2254
        {
 
2255
        $$hash{'allow_freeze'} = "true";
 
2256
        }
 
2257
      delete $$hash{'allow_system_actions'};
 
2258
 
 
2259
      # If file_directory is defined, use it to qualify relative paths; if not,
 
2260
      # and check_local_user is defined, use $home. Remove file_directory from
 
2261
      # the output.
 
2262
 
 
2263
      $dir = "";
 
2264
      if (defined $$hash{"file_directory"})
 
2265
        {
 
2266
        $dir = $$hash{"file_directory"} . "/";
 
2267
        delete $$hash{"file_directory"};
 
2268
        }
 
2269
      elsif ($$hash{"check_local_user"} eq "true")
 
2270
        {
 
2271
        $dir = "\$home/";
 
2272
        }
 
2273
 
 
2274
      # If it begins with an upper case letter, guess that this is really
 
2275
      # a macro.
 
2276
 
 
2277
      if (defined $$hash{"file"} && $$hash{"file"} !~ /^[\/A-Z]/)
 
2278
        {
 
2279
        $$hash{"file"} = $dir . $$hash{"file"};
 
2280
        }
 
2281
      }
 
2282
 
 
2283
 
 
2284
    # ---- Changes to localuser director ----
 
2285
 
 
2286
    elsif ($driver eq "localuser")
 
2287
      {
 
2288
      &abolished($hash, "A localuser director", "match_directory");
 
2289
      $$hash{"driver"} = "accept";
 
2290
      $$hash{"check_local_user"} = "true";
 
2291
      }
 
2292
 
 
2293
 
 
2294
    # ---- Changes to smartuser director ----
 
2295
 
 
2296
    elsif ($driver eq "smartuser")
 
2297
      {
 
2298
      &abolished($hash, "A smartuser director", "panic_expansion_fail");
 
2299
 
 
2300
      $transport = $$hash{"transport"};
 
2301
      $new_address = $$hash{"new_address"};
 
2302
 
 
2303
      if (defined $transport && defined $new_address)
 
2304
        {
 
2305
        &rubric();
 
2306
        print STDERR "\n" .
 
2307
"** The Exim 3 configuration contains a smartuser director called '$name',\n".
 
2308
"   which has both 'transport' and 'new_address' set. This has been turned\n".
 
2309
"   into two routers for Exim 4. However, if the new address contains a\n" .
 
2310
"   reference to \$local_part, this won't work correctly. In any case, you\n".
 
2311
"   may be able to make it tidier by rewriting.\n";
 
2312
        $$hash{"driver"} = "redirect";
 
2313
        $$hash{"data"} = $new_address;
 
2314
        $$hash{"redirect_router"} = "${name}_part2";
 
2315
 
 
2316
        $second_router = "\n".
 
2317
          "#!!# This router is invented to go with the previous one because\n".
 
2318
          "#!!# in Exim 4 you can't have a change of address and a transport\n".
 
2319
          "#!!# setting in the same router as you could in Exim 3.\n\n" .
 
2320
          "${name}_part2:\n".
 
2321
          "  driver = accept\n".
 
2322
          "  condition = \$\{if eq\{\$local_part@\$domain\}" .
 
2323
          "\{$new_address\}\{yes\}\{no\}\}\n".
 
2324
          "  transport = $$hash{'transport'}\n";
 
2325
 
 
2326
        delete $$hash{"new_address"};
 
2327
        delete $$hash{"transport"};
 
2328
        }
 
2329
      elsif (defined $new_address)
 
2330
        {
 
2331
        $$hash{"driver"} = "redirect";
 
2332
        $$hash{"data"} = $new_address;
 
2333
        $$hash{"allow_defer"} = "true";
 
2334
        $$hash{"allow_fail"} = "true";
 
2335
        delete $$hash{"new_address"};
 
2336
        }
 
2337
      else     # Includes the case of neither set (verify_only)
 
2338
        {
 
2339
        $$hash{"driver"} = "accept";
 
2340
        if (defined $$hash{"rewrite"})
 
2341
          {
 
2342
          &rubric();
 
2343
          print STDERR "\n" .
 
2344
"** The Exim 3 configuration contains a setting of the 'rewrite' option on\n".
 
2345
"   a smartuser director called '$name', but this director does not have\n".
 
2346
"   a setting of 'new_address', so 'rewrite' has no effect. The director\n".
 
2347
"   has been turned into an 'accept' router, and 'rewrite' has been discarded.";
 
2348
          delete $$hash{"rewrite"};
 
2349
          }
 
2350
        }
 
2351
      }
 
2352
 
 
2353
 
 
2354
    # -------------------------------------
 
2355
 
 
2356
    # For ex-directors that don't have check_local_user set, add
 
2357
    # retry_use_local_part to imitate what Exim 3 would have done.
 
2358
 
 
2359
    $$hash{"retry_use_local_part"} = "true"
 
2360
      if (!defined $$hash{"check_local_user"} ||
 
2361
          $$hash{"check_local_user"} eq "false") ;
 
2362
 
 
2363
    # Output the router's option settings
 
2364
 
 
2365
    &outdriver($hash);
 
2366
 
 
2367
    # Output an auxiliary router if one is needed
 
2368
 
 
2369
    print STDOUT $second_router if defined $second_router;
 
2370
 
 
2371
    next;
 
2372
    }
 
2373
 
 
2374
  # Skip past any continuation lines for an option setting
 
2375
  while ($c[$i] =~ /\\\s*$/s)
 
2376
    {
 
2377
    $i++;
 
2378
    $i++ while ($c[$i] =~ /^\s*#/);
 
2379
    }
 
2380
  }
 
2381
 
 
2382
 
 
2383
 
 
2384
# -------- The transports configuration --------
 
2385
 
 
2386
$started = 0;
 
2387
$prefix = "t.";
 
2388
for ($i = $transport_start; $i < $clen; $i++)
 
2389
  {
 
2390
  $type = &checkline($c[$i]);
 
2391
  last if $type eq "end";
 
2392
 
 
2393
  if ($type eq "comment") { print STDOUT "$c[$i]\n"; next; }
 
2394
 
 
2395
  if (!$started)
 
2396
    {
 
2397
    print STDOUT "begin transports\n\n";
 
2398
    $started = 1;
 
2399
    }
 
2400
 
 
2401
  if ($type eq "driver")
 
2402
    {
 
2403
    $hash = $driverlist{"$prefix$name"};
 
2404
    $driver = $$hash{"driver"};
 
2405
    print STDOUT "$name:\n";
 
2406
 
 
2407
    # ---- Changes to the appendfile transport ----
 
2408
 
 
2409
    if ($driver eq "appendfile")
 
2410
      {
 
2411
      &renamed($hash, "prefix", "message_prefix");
 
2412
      &renamed($hash, "suffix", "message_suffix");
 
2413
      &abolished($hash, "An appendfile transport",
 
2414
        "require_lockfile");
 
2415
      &handle_batch_and_bsmtp($hash);
 
2416
      if (defined $$hash{"from_hack"} && $$hash{"from_hack"} eq "false")
 
2417
        {
 
2418
        print STDOUT "#!!# no_from_hack replaced by check_string\n";
 
2419
        $$hash{"check_string"} = "";
 
2420
        }
 
2421
      delete $$hash{"from_hack"};
 
2422
      }
 
2423
 
 
2424
    # ---- Changes to the lmtp transport ----
 
2425
 
 
2426
    elsif ($driver eq "lmtp")
 
2427
      {
 
2428
      if (defined $$hash{"batch"} && $$hash{"batch"} ne "none")
 
2429
        {
 
2430
        $$hash{"batch_max"} = "100" if !defined $$hash{"batch_max"};
 
2431
        $$hash{"batch_id"} = "\$domain" if $$hash{"batch"} eq "domain";
 
2432
        }
 
2433
      else
 
2434
        {
 
2435
        $$hash{"batch_max"} = "1" if defined $$hash{"batch_max"};
 
2436
        }
 
2437
      delete $$hash{"batch"};
 
2438
      }
 
2439
 
 
2440
    # ---- Changes to the pipe transport ----
 
2441
 
 
2442
    elsif ($driver eq "pipe")
 
2443
      {
 
2444
      &renamed($hash, "prefix", "message_prefix");
 
2445
      &renamed($hash, "suffix", "message_suffix");
 
2446
      &handle_batch_and_bsmtp($hash);
 
2447
      if (defined $$hash{"from_hack"} && $$hash{"from_hack"} eq "false")
 
2448
        {
 
2449
        print STDOUT "#!!# no_from_hack replaced by check_string\n";
 
2450
        $$hash{"check_string"} = "";
 
2451
        }
 
2452
      delete $$hash{"from_hack"};
 
2453
      }
 
2454
 
 
2455
    # ---- Changes to the smtp transport ----
 
2456
 
 
2457
    elsif ($driver eq "smtp")
 
2458
      {
 
2459
      &abolished($hash, "An smtp transport", "mx_domains");
 
2460
      &renamed($hash, "service", "port");
 
2461
      &renamed($hash, "tls_verify_ciphers", "tls_require_ciphers");
 
2462
      &renamed($hash, "authenticate_hosts", "hosts_try_auth");
 
2463
 
 
2464
      if (defined $$hash{"batch_max"})
 
2465
        {
 
2466
        print STDOUT "#!!# batch_max renamed connection_max_messages\n";
 
2467
        $$hash{"connection_max_messages"} = $$hash{"batch_max"};
 
2468
        delete $$hash{"batch_max"};
 
2469
        }
 
2470
 
 
2471
      foreach $o ("hosts_try_auth", "hosts_avoid_tls", "hosts_require_tls",
 
2472
                  "mx_domains", "serialize_hosts")
 
2473
        {
 
2474
        $$hash{$o} = &no_expand_regex($$hash{$o}) if defined $$hash{$o};
 
2475
        }
 
2476
      }
 
2477
 
 
2478
    &outdriver($driverlist{"$prefix$name"});
 
2479
    next;
 
2480
    }
 
2481
 
 
2482
  # Skip past any continuation lines for an option setting
 
2483
  while ($c[$i] =~ /\\\s*$/s)
 
2484
    {
 
2485
    $i++;
 
2486
    $i++ while ($c[$i] =~ /^\s*#/);
 
2487
    }
 
2488
  }
 
2489
 
 
2490
 
 
2491
# -------- The retry configuration --------
 
2492
 
 
2493
$started = 0;
 
2494
for ($i = $retry_start; $i < $clen && $i < $rewrite_start - 1; $i++)
 
2495
  {
 
2496
  if (!$started)
 
2497
    {
 
2498
    if ($c[$i] !~ /^\s*(#|$)/)
 
2499
      {
 
2500
      print STDOUT "\nbegin retry\n\n";
 
2501
      $started = 1;
 
2502
      }
 
2503
    }
 
2504
  &print_no_expand($c[$i]);
 
2505
  }
 
2506
 
 
2507
print STDOUT "\n# End of Exim 4 configuration\n";
 
2508
 
 
2509
print STDERR "\n*******************************************************\n";
 
2510
print STDERR   "***** Please review the generated file carefully. *****\n";
 
2511
print STDERR   "*******************************************************\n\n";
 
2512
 
 
2513
# End of convert4r4
 
2514