~ubuntu-branches/ubuntu/raring/postfix/raring

« back to all changes in this revision

Viewing changes to src/cleanup/cleanup_message.c

Tags: upstream-2.2.6
ImportĀ upstreamĀ versionĀ 2.2.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
161
161
    TOK822 *tree;
162
162
    TOK822 **addr_list;
163
163
    TOK822 **tpp;
 
164
    int     did_rewrite = 0;
164
165
 
165
166
    if (msg_verbose)
166
167
        msg_info("rewrite_sender: %s", hdr_opts->name);
167
168
 
168
169
    /*
169
 
     * Parse the header line, rewrite each address found, save copies of
170
 
     * sender addresses, and regenerate the header line. Finally, pipe the
171
 
     * result through the header line folding routine.
 
170
     * Parse the header line, rewrite each address found, and regenerate the
 
171
     * header line. Finally, pipe the result through the header line folding
 
172
     * routine.
172
173
     */
173
174
    tree = tok822_parse_limit(vstring_str(header_buf)
174
175
                              + strlen(hdr_opts->name) + 1,
175
176
                              var_token_limit);
176
177
    addr_list = tok822_grep(tree, TOK822_ADDR);
177
178
    for (tpp = addr_list; *tpp; tpp++) {
178
 
        cleanup_rewrite_tree(*tpp);
 
179
        did_rewrite |= cleanup_rewrite_tree(state->hdr_rewrite_context, *tpp);
179
180
        if (state->flags & CLEANUP_FLAG_MAP_OK) {
180
 
            if (cleanup_send_canon_maps)
181
 
                cleanup_map11_tree(state, *tpp, cleanup_send_canon_maps,
 
181
            if (cleanup_send_canon_maps
 
182
                && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_HDR_FROM))
 
183
                did_rewrite |=
 
184
                    cleanup_map11_tree(state, *tpp, cleanup_send_canon_maps,
182
185
                                cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
183
 
            if (cleanup_comm_canon_maps)
184
 
                cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
 
186
            if (cleanup_comm_canon_maps
 
187
                && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_HDR_FROM))
 
188
                did_rewrite |=
 
189
                    cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
185
190
                                cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
186
191
            if (cleanup_masq_domains
187
192
                && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_FROM))
188
 
                cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
 
193
                did_rewrite |=
 
194
                    cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
189
195
        }
190
 
        if (hdr_opts->type == HDR_FROM && state->from == 0)
191
 
            state->from = cleanup_extract_internal(header_buf, *tpp);
192
 
        if (hdr_opts->type == HDR_RESENT_FROM && state->resent_from == 0)
193
 
            state->resent_from =
194
 
                cleanup_extract_internal(header_buf, *tpp);
195
 
#if 0
196
 
        if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt)
197
 
            state->return_receipt =
198
 
                cleanup_extract_internal(header_buf, *tpp);
199
 
#endif
200
 
        if (var_enable_errors_to)
201
 
            if (hdr_opts->type == HDR_ERRORS_TO && !state->errors_to)
202
 
                state->errors_to =
203
 
                    cleanup_extract_internal(header_buf, *tpp);
204
 
    }
205
 
    vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
206
 
    tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
 
196
    }
 
197
    if (did_rewrite) {
 
198
        vstring_truncate(header_buf, strlen(hdr_opts->name));
 
199
        vstring_strcat(header_buf, ": ");
 
200
        tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
 
201
    }
207
202
    myfree((char *) addr_list);
208
203
    tok822_free_tree(tree);
209
 
    if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
210
 
        cleanup_fold_header(state, header_buf);
 
204
    if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
 
205
        if (did_rewrite)
 
206
            cleanup_fold_header(state, header_buf);
 
207
        else
 
208
            cleanup_out_header(state, header_buf);
 
209
    }
211
210
}
212
211
 
213
212
/* cleanup_rewrite_recip - recipient address rewriting */
218
217
    TOK822 *tree;
219
218
    TOK822 **addr_list;
220
219
    TOK822 **tpp;
 
220
    int     did_rewrite = 0;
221
221
 
222
222
    if (msg_verbose)
223
223
        msg_info("rewrite_recip: %s", hdr_opts->name);
224
224
 
225
225
    /*
226
 
     * Parse the header line, rewrite each address found, save copies of
227
 
     * recipient addresses, and regenerate the header line. Finally, pipe the
228
 
     * result through the header line folding routine.
 
226
     * Parse the header line, rewrite each address found, and regenerate the
 
227
     * header line. Finally, pipe the result through the header line folding
 
228
     * routine.
229
229
     */
230
230
    tree = tok822_parse_limit(vstring_str(header_buf)
231
231
                              + strlen(hdr_opts->name) + 1,
232
232
                              var_token_limit);
233
233
    addr_list = tok822_grep(tree, TOK822_ADDR);
234
234
    for (tpp = addr_list; *tpp; tpp++) {
235
 
        cleanup_rewrite_tree(*tpp);
 
235
        did_rewrite |= cleanup_rewrite_tree(state->hdr_rewrite_context, *tpp);
236
236
        if (state->flags & CLEANUP_FLAG_MAP_OK) {
237
 
            if (cleanup_rcpt_canon_maps)
238
 
                cleanup_map11_tree(state, *tpp, cleanup_rcpt_canon_maps,
239
 
                                cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
240
 
            if (cleanup_comm_canon_maps)
241
 
                cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
242
 
                                cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
243
 
 
 
237
            if (cleanup_rcpt_canon_maps
 
238
                && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_HDR_RCPT))
 
239
                did_rewrite |=
 
240
                    cleanup_map11_tree(state, *tpp, cleanup_rcpt_canon_maps,
 
241
                                cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
 
242
            if (cleanup_comm_canon_maps
 
243
                && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_HDR_RCPT))
 
244
                did_rewrite |=
 
245
                    cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
 
246
                                cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
244
247
            if (cleanup_masq_domains
245
248
                && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT))
246
 
                cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
 
249
                did_rewrite |=
 
250
                    cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
247
251
        }
248
252
    }
249
 
    vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
250
 
    tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
 
253
    if (did_rewrite) {
 
254
        vstring_truncate(header_buf, strlen(hdr_opts->name));
 
255
        vstring_strcat(header_buf, ": ");
 
256
        tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
 
257
    }
251
258
    myfree((char *) addr_list);
252
259
    tok822_free_tree(tree);
253
 
    if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
254
 
        cleanup_fold_header(state, header_buf);
 
260
    if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
 
261
        if (did_rewrite)
 
262
            cleanup_fold_header(state, header_buf);
 
263
        else
 
264
            cleanup_out_header(state, header_buf);
 
265
    }
255
266
}
256
267
 
257
268
/* cleanup_act_log - log action with context */
284
295
 
285
296
/* cleanup_act - act upon a header/body match */
286
297
 
287
 
static int cleanup_act(CLEANUP_STATE *state, char *context, const char *buf,
288
 
                               const char *value, const char *map_class)
 
298
static const char *cleanup_act(CLEANUP_STATE *state, char *context,
 
299
                                       const char *buf, const char *value,
 
300
                                       const char *map_class)
289
301
{
290
302
    const char *optional_text = value + strcspn(value, " \t");
291
303
    int     command_len = optional_text - value;
294
306
        optional_text++;
295
307
 
296
308
#define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0)
297
 
#define CLEANUP_ACT_KEEP 1
298
309
#define CLEANUP_ACT_DROP 0
299
310
 
300
311
    if (STREQUAL(value, "REJECT", command_len)) {
304
315
        state->errs |= CLEANUP_STAT_CONT;
305
316
        state->flags &= ~CLEANUP_FLAG_FILTER;
306
317
        cleanup_act_log(state, "reject", context, buf, state->reason);
307
 
        return (CLEANUP_ACT_KEEP);
 
318
        return (buf);
308
319
    }
309
320
    if (STREQUAL(value, "WARN", command_len)) {
310
321
        cleanup_act_log(state, "warning", context, buf, optional_text);
311
 
        return (CLEANUP_ACT_KEEP);
 
322
        return (buf);
312
323
    }
313
324
    if (STREQUAL(value, "FILTER", command_len)) {
314
325
        if (*optional_text == 0) {
315
326
            msg_warn("missing FILTER command argument in %s map", map_class);
316
327
        } else if (strchr(optional_text, ':') == 0) {
317
 
            msg_warn("bad FILTER command %s in %s, need transport:destination",
 
328
            msg_warn("bad FILTER command %s in %s -- "
 
329
                     "need transport:destination",
318
330
                     optional_text, map_class);
319
331
        } else {
320
332
            if (state->filter)
322
334
            state->filter = mystrdup(optional_text);
323
335
            cleanup_act_log(state, "filter", context, buf, optional_text);
324
336
        }
325
 
        return (CLEANUP_ACT_KEEP);
 
337
        return (buf);
326
338
    }
327
339
    if (STREQUAL(value, "DISCARD", command_len)) {
328
340
        cleanup_act_log(state, "discard", context, buf, optional_text);
329
341
        state->flags |= CLEANUP_FLAG_DISCARD;
330
342
        state->flags &= ~CLEANUP_FLAG_FILTER;
331
 
        return (CLEANUP_ACT_KEEP);
 
343
        return (buf);
332
344
    }
333
345
    if (STREQUAL(value, "HOLD", command_len)) {
334
346
        cleanup_act_log(state, "hold", context, buf, optional_text);
335
347
        state->flags |= CLEANUP_FLAG_HOLD;
336
 
        return (CLEANUP_ACT_KEEP);
 
348
        return (buf);
337
349
    }
338
350
    if (STREQUAL(value, "PREPEND", command_len)) {
339
351
        if (*optional_text == 0) {
340
352
            msg_warn("PREPEND action without text in %s map", map_class);
341
353
        } else if (strcmp(context, CLEANUP_ACT_CTXT_HEADER) == 0
342
354
                   && !is_header(optional_text)) {
343
 
            msg_warn("bad PREPEND header text \"%s\" in %s map, "
 
355
            msg_warn("bad PREPEND header text \"%s\" in %s map -- "
344
356
                     "need \"headername: headervalue\"",
345
357
                     optional_text, map_class);
346
358
        } else {
347
359
            cleanup_act_log(state, "prepend", context, buf, optional_text);
348
360
            cleanup_out_string(state, REC_TYPE_NORM, optional_text);
349
361
        }
350
 
        return (CLEANUP_ACT_KEEP);
 
362
        return (buf);
 
363
    }
 
364
    if (STREQUAL(value, "REPLACE", command_len)) {
 
365
        if (*optional_text == 0) {
 
366
            msg_warn("REPLACE action without text in %s map", map_class);
 
367
            return (buf);
 
368
        } else if (strcmp(context, CLEANUP_ACT_CTXT_HEADER) == 0
 
369
                   && !is_header(optional_text)) {
 
370
            msg_warn("bad REPLACE header text \"%s\" in %s map -- "
 
371
                     "need \"headername: headervalue\"",
 
372
                     optional_text, map_class);
 
373
            return (buf);
 
374
        } else {
 
375
            cleanup_act_log(state, "replace", context, buf, optional_text);
 
376
            return (mystrdup(optional_text));
 
377
        }
351
378
    }
352
379
    if (STREQUAL(value, "REDIRECT", command_len)) {
353
380
        if (strchr(optional_text, '@') == 0) {
354
 
            msg_warn("bad REDIRECT target \"%s\" in %s map, need user@domain",
 
381
            msg_warn("bad REDIRECT target \"%s\" in %s map -- "
 
382
                     "need user@domain",
355
383
                     optional_text, map_class);
356
384
        } else {
357
385
            if (state->redirect)
360
388
            cleanup_act_log(state, "redirect", context, buf, optional_text);
361
389
            state->flags &= ~CLEANUP_FLAG_FILTER;
362
390
        }
363
 
        return (CLEANUP_ACT_KEEP);
 
391
        return (buf);
364
392
    }
365
393
    /* Allow and ignore optional text after the action. */
366
394
 
368
396
        return (CLEANUP_ACT_DROP);
369
397
 
370
398
    if (STREQUAL(value, "DUNNO", command_len))  /* preferred */
371
 
        return (CLEANUP_ACT_KEEP);
 
399
        return (buf);
372
400
 
373
401
    if (STREQUAL(value, "OK", command_len))     /* compat */
374
 
        return (CLEANUP_ACT_KEEP);
 
402
        return (buf);
375
403
 
376
404
    msg_warn("unknown command in %s map: %s", map_class, value);
377
 
    return (CLEANUP_ACT_KEEP);
 
405
    return (buf);
378
406
}
379
407
 
380
408
/* cleanup_header_callback - process one complete header line */
423
451
        const char *value;
424
452
 
425
453
        if ((value = maps_find(checks, header, 0)) != 0) {
426
 
            if (cleanup_act(state, CLEANUP_ACT_CTXT_HEADER,
427
 
                            header, value, map_class)
428
 
                == CLEANUP_ACT_DROP)
 
454
            const char *result;
 
455
 
 
456
            if ((result = cleanup_act(state, CLEANUP_ACT_CTXT_HEADER,
 
457
                                      header, value, map_class))
 
458
                == CLEANUP_ACT_DROP) {
429
459
                return;
 
460
            } else if (result != header) {
 
461
                vstring_strcpy(header_buf, result);
 
462
                hdr_opts = header_opts_find(result);
 
463
                myfree((char *) result);
 
464
            }
430
465
        }
431
466
    }
432
467
 
508
543
        if (CLEANUP_OUT_OK(state)) {
509
544
            if (hdr_opts->flags & HDR_OPT_RR)
510
545
                state->resent = "Resent-";
511
 
            if (hdr_opts->flags & HDR_OPT_SENDER) {
 
546
            if ((hdr_opts->flags & HDR_OPT_SENDER)
 
547
                && state->hdr_rewrite_context) {
512
548
                cleanup_rewrite_sender(state, hdr_opts, header_buf);
513
 
            } else if (hdr_opts->flags & HDR_OPT_RECIP) {
 
549
            } else if ((hdr_opts->flags & HDR_OPT_RECIP)
 
550
                       && state->hdr_rewrite_context) {
514
551
                cleanup_rewrite_recip(state, hdr_opts, header_buf);
515
552
            } else if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
516
553
                cleanup_out_header(state, header_buf);
527
564
    char    time_stamp[1024];           /* XXX locale dependent? */
528
565
    struct tm *tp;
529
566
    TOK822 *token;
 
567
    time_t  tv;
530
568
 
531
569
    /*
532
570
     * Add a missing (Resent-)Message-Id: header. The message ID gives the
536
574
     * 
537
575
     * XXX It is the queue ID non-inode bits that prevent messages from getting
538
576
     * the same Message-Id within the same second.
 
577
     * 
 
578
     * XXX An arbitrary amount of time may pass between the start of the mail
 
579
     * transaction and the creation of a queue file. Since we guarantee queue
 
580
     * ID uniqueness only within a second, we must ensure that the time in
 
581
     * the message ID matches the queue ID creation time, as long as we use
 
582
     * the queue ID in the message ID.
539
583
     */
540
584
    if ((state->headers_seen & (1 << (state->resent[0] ?
541
585
                           HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) {
542
 
        tp = gmtime(&state->time);
 
586
        tv = state->handle->ctime.tv_sec;
 
587
        tp = gmtime(&tv);
543
588
        strftime(time_stamp, sizeof(time_stamp), "%Y%m%d%H%M%S", tp);
544
589
        cleanup_out_format(state, REC_TYPE_NORM, "%sMessage-Id: <%s.%s@%s>",
545
590
                state->resent, time_stamp, state->queue_id, var_myhostname);
630
675
        const char *value;
631
676
 
632
677
        if ((value = maps_find(cleanup_body_checks, buf, 0)) != 0) {
633
 
            if (cleanup_act(state, CLEANUP_ACT_CTXT_BODY,
634
 
                            buf, value, VAR_BODY_CHECKS)
635
 
                == CLEANUP_ACT_DROP)
636
 
                return;
 
678
            const char *result;
 
679
 
 
680
            if ((result = cleanup_act(state, CLEANUP_ACT_CTXT_BODY,
 
681
                                      buf, value, VAR_BODY_CHECKS))
 
682
                == CLEANUP_ACT_DROP) {
 
683
                return;
 
684
            } else if (result != buf) {
 
685
                cleanup_out(state, type, result, strlen(result));
 
686
                myfree((char *) result);
 
687
                return;
 
688
            }
637
689
        }
638
690
    }
639
691
    cleanup_out(state, type, buf, len);