~ubuntu-branches/ubuntu/quantal/dovecot/quantal

« back to all changes in this revision

Viewing changes to sieve/src/lib-sieve/plugins/notify/cmd-notify.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2010-06-29 09:21:32 UTC
  • mfrom: (4.1.14 sid)
  • Revision ID: james.westby@ubuntu.com-20100629092132-q4pr5lfuvmjqou19
Tags: 1:1.2.12-1ubuntu1
* Merge from Debian Unstable, remaining changes:
  + Add mail-stack-delivery as per server-maverick-mail-integration spec:
   - Update debian/rules
   - Convert existing package to a dummy package and add new binary in debian/control
   - Update maintainer scripts.
   - Move previously installed backups and config files to new package name
     space in preinst
   - Add new debian/mail-stack-delivery.prerm to handle downgrades
   - Rename debian/dovecot-postfix.* to debian/mail-stack-delivery.*
  + Use Snakeoil SSL certificates by default.
    - debian/control: Depend on ssl-cert.
    - debian/patches/ssl-cert-snakeoil.dpatch: Change default SSL cert paths to snakeoil.
    - debian/dovecot-common.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - Created debian/dovecot-common.ufw.profile.
    - debian/rules: install profile.
    - debian/control: suggest ufw.
  + debian/{control,rules}: enable PIE hardening.
  + debian/control: Update Vcs-* headers.
  + Add SMTP-AUTH support for Outlook (login auth mechanism) 
  + debian/dovecot-common.dirs: Added usr/share/doc/dovecot-common
  + debian/patches/fix-dovecot-config-parser.patch: Fix ordering of external config 
    files. (LP: #597818)

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
static bool cmd_notify_validate
46
46
        (struct sieve_validator *valdtr, struct sieve_command *cmd);
47
47
static bool cmd_notify_generate
48
 
        (const struct sieve_codegen_env *cgenv, 
 
48
        (const struct sieve_codegen_env *cgenv,
49
49
                struct sieve_command *ctx);
50
50
 
51
51
const struct sieve_command_def cmd_notify_old = {
55
55
        cmd_notify_registered,
56
56
        cmd_notify_pre_validate,
57
57
        cmd_notify_validate,
58
 
        cmd_notify_generate, 
 
58
        cmd_notify_generate,
59
59
        NULL,
60
60
};
61
61
 
69
69
        (struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
70
70
                struct sieve_command *cmd);
71
71
static bool cmd_notify_validate_stringlist_tag
72
 
        (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
 
72
        (struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
73
73
                struct sieve_command *cmd);
74
74
 
75
75
/* Argument objects */
81
81
        NULL, NULL, NULL
82
82
};
83
83
 
84
 
static const struct sieve_argument_def notify_options_tag = { 
85
 
        "options", 
86
 
        NULL, 
87
 
        cmd_notify_validate_stringlist_tag, 
88
 
        NULL, NULL, NULL 
 
84
static const struct sieve_argument_def notify_options_tag = {
 
85
        "options",
 
86
        NULL,
 
87
        cmd_notify_validate_stringlist_tag,
 
88
        NULL, NULL, NULL
89
89
};
90
90
 
91
91
static const struct sieve_argument_def notify_id_tag = {
102
102
        NULL, NULL, NULL
103
103
};
104
104
 
105
 
/* 
106
 
 * Notify operation 
 
105
/*
 
106
 * Notify operation
107
107
 */
108
108
 
109
109
static bool cmd_notify_operation_dump
111
111
static int cmd_notify_operation_execute
112
112
        (const struct sieve_runtime_env *renv, sieve_size_t *address);
113
113
 
114
 
const struct sieve_operation_def notify_old_operation = { 
 
114
const struct sieve_operation_def notify_old_operation = {
115
115
        "NOTIFY",
116
116
        &notify_extension,
117
117
        EXT_NOTIFY_OPERATION_NOTIFY,
118
 
        cmd_notify_operation_dump, 
 
118
        cmd_notify_operation_dump,
119
119
        cmd_notify_operation_execute
120
120
};
121
121
 
129
129
  OPT_ID
130
130
};
131
131
 
132
 
/* 
133
 
 * Notify action 
 
132
/*
 
133
 * Notify action
134
134
 */
135
135
 
136
136
/* Forward declarations */
137
137
 
138
138
static int act_notify_check_duplicate
139
 
        (const struct sieve_runtime_env *renv, 
 
139
        (const struct sieve_runtime_env *renv,
140
140
                const struct sieve_action *act,
141
141
                const struct sieve_action *act_other);
142
142
static void act_notify_print
143
143
        (const struct sieve_action *action, const struct sieve_result_print_env *rpenv,
144
 
                bool *keep);    
 
144
                bool *keep);
145
145
static bool act_notify_commit
146
 
        (const struct sieve_action *action,     const struct sieve_action_exec_env *aenv, 
 
146
        (const struct sieve_action *action,     const struct sieve_action_exec_env *aenv,
147
147
                void *tr_context, bool *keep);
148
148
 
149
149
/* Action object */
152
152
        "notify",
153
153
        0,
154
154
        NULL,
155
 
        act_notify_check_duplicate, 
 
155
        act_notify_check_duplicate,
156
156
        NULL,
157
157
        act_notify_print,
158
158
        NULL, NULL,
197
197
 
198
198
        if ( sieve_argument_is(tag, notify_method_tag) ) {
199
199
                ctx_data->method = *arg;
200
 
        
 
200
 
201
201
                /* Removed */
202
202
                *arg = sieve_ast_arguments_detach(*arg, 1);
203
203
 
218
218
}
219
219
 
220
220
static bool cmd_notify_validate_stringlist_tag
221
 
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
 
221
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
222
222
        struct sieve_command *cmd)
223
223
{
224
224
        struct sieve_ast_argument *tag = *arg;
225
 
        struct cmd_notify_context_data *ctx_data = 
226
 
                (struct cmd_notify_context_data *) cmd->data; 
 
225
        struct cmd_notify_context_data *ctx_data =
 
226
                (struct cmd_notify_context_data *) cmd->data;
227
227
 
228
228
        /* Detach the tag itself */
229
229
        *arg = sieve_ast_arguments_detach(*arg,1);
230
 
        
 
230
 
231
231
        /* Check syntax:
232
232
         *   :options string-list
233
233
         */
234
234
        if ( !sieve_validate_tag_parameter
235
 
                (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING_LIST, FALSE) ) 
 
235
                (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING_LIST, FALSE) )
236
236
                return FALSE;
237
 
                
 
237
 
238
238
        /* Assign context */
239
 
        ctx_data->options = *arg;       
240
 
        
 
239
        ctx_data->options = *arg;
 
240
 
241
241
        /* Skip parameter */
242
242
        *arg = sieve_ast_argument_next(*arg);
243
243
 
275
275
        struct sieve_command *cmd)
276
276
{
277
277
        struct cmd_notify_context_data *ctx_data;
278
 
        
 
278
 
279
279
        /* Create context */
280
280
        ctx_data = p_new(sieve_command_pool(cmd),       struct cmd_notify_context_data, 1);
281
281
        cmd->data = ctx_data;
319
319
        /* Check :method argument */
320
320
        if ( ctx_data->method != NULL ) {
321
321
                const char *method = sieve_ast_argument_strc(ctx_data->method);
322
 
                
 
322
 
323
323
                if ( strcasecmp(method, "mailto") != 0 ) {
324
324
                        sieve_command_validate_error(valdtr, cmd,
325
325
                                "the notify command of the deprecated notify extension "
331
331
        /* Check :options argument */
332
332
        if ( ctx_data->options != NULL ) {
333
333
                struct sieve_ast_argument *option = ctx_data->options;
334
 
                
 
334
 
335
335
                /* Parse and check options */
336
336
                if ( sieve_ast_stringlist_map
337
337
                        (&option, (void *) valdtr, cmd_notify_address_validate) <= 0 ) {
361
361
        return sieve_generate_arguments(cgenv, cmd, NULL);
362
362
}
363
363
 
364
 
/* 
 
364
/*
365
365
 * Code dump
366
366
 */
367
 
 
 
367
 
368
368
static bool cmd_notify_operation_dump
369
369
(const struct sieve_dumptime_env *denv, sieve_size_t *address)
370
 
{       
 
370
{
371
371
        int opt_code = 1;
372
 
        
 
372
 
373
373
        sieve_code_dumpf(denv, "NOTIFY");
374
 
        sieve_code_descend(denv);       
 
374
        sieve_code_descend(denv);
375
375
 
376
376
        /* Source line */
377
377
        if ( !sieve_code_source_line_dump(denv, address) )
381
381
        if ( sieve_operand_optional_present(denv->sbin, address) ) {
382
382
                while ( opt_code != 0 ) {
383
383
                        sieve_code_mark(denv);
384
 
                        
385
 
                        if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) 
 
384
 
 
385
                        if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) )
386
386
                                return FALSE;
387
387
 
388
388
                        switch ( opt_code ) {
409
409
                        }
410
410
                }
411
411
        }
412
 
        
 
412
 
413
413
        return TRUE;
414
414
}
415
415
 
416
 
/* 
 
416
/*
417
417
 * Code execution
418
418
 */
419
419
 
420
 
 
 
420
 
421
421
static int cmd_notify_operation_execute
422
422
(const struct sieve_runtime_env *renv, sieve_size_t *address)
423
 
{       
 
423
{
424
424
        const struct sieve_extension *this_ext = renv->oprtn.ext;
425
425
        struct ext_notify_action *act;
426
426
        pool_t pool;
427
427
        int opt_code = 1;
428
428
        sieve_number_t importance = 1;
429
429
        struct sieve_coded_stringlist *options = NULL;
430
 
        string_t *message = NULL, *id = NULL; 
 
430
        string_t *message = NULL, *id = NULL;
431
431
        unsigned int source_line;
432
432
 
433
433
        /*
434
434
         * Read operands
435
435
         */
436
 
                
 
436
 
437
437
        /* Source line */
438
438
        if ( !sieve_code_source_line_read(renv, address, &source_line) ) {
439
439
                sieve_runtime_trace_error(renv, "invalid source line");
440
440
                return SIEVE_EXEC_BIN_CORRUPT;
441
441
        }
442
 
        
443
 
        /* Optional operands */ 
 
442
 
 
443
        /* Optional operands */
444
444
        if ( sieve_operand_optional_present(renv->sbin, address) ) {
445
445
                while ( opt_code != 0 ) {
446
446
                        if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) {
456
456
                                        sieve_runtime_trace_error(renv, "invalid importance operand");
457
457
                                        return SIEVE_EXEC_BIN_CORRUPT;
458
458
                                }
459
 
        
 
459
 
460
460
                                /* Enforce 0 < importance < 4 (just to be sure) */
461
 
                                if ( importance < 1 ) 
 
461
                                if ( importance < 1 )
462
462
                                        importance = 1;
463
463
                                else if ( importance > 3 )
464
464
                                        importance = 3;
482
482
                                }
483
483
                                break;
484
484
                        default:
485
 
                                sieve_runtime_trace_error(renv, "unknown optional operand: %d", 
 
485
                                sieve_runtime_trace_error(renv, "unknown optional operand: %d",
486
486
                                        opt_code);
487
487
                                return SIEVE_EXEC_BIN_CORRUPT;
488
488
                        }
489
489
                }
490
490
        }
491
 
                
 
491
 
492
492
        /*
493
493
         * Perform operation
494
494
         */
495
495
 
496
 
        sieve_runtime_trace(renv, "NOTIFY action");     
 
496
        sieve_runtime_trace(renv, "NOTIFY action");
497
497
 
498
498
        /* Compose action */
499
499
        if ( options != NULL ) {
500
500
                string_t *raw_address;
501
501
                string_t *out_message;
502
 
                bool result;    
 
502
                bool result;
503
503
 
504
504
                pool = sieve_result_pool(renv->result);
505
505
                act = p_new(pool, struct ext_notify_action, 1);
506
506
                if ( id != NULL )
507
507
                                act->id = p_strdup(pool, str_c(id));
508
 
                act->importance = importance;           
509
 
        
 
508
                act->importance = importance;
 
509
 
510
510
                /* Process message */
511
511
 
512
512
                out_message = t_str_new(1024);
513
513
                ext_notify_construct_message
514
514
                        (renv, (message == NULL ? NULL : str_c(message)), out_message);
515
515
                act->message = p_strdup(pool, str_c(out_message));
516
 
                
517
 
                /* Normalize and verify all :options addresses */                                       
 
516
 
 
517
                /* Normalize and verify all :options addresses */
518
518
 
519
519
                sieve_coded_stringlist_reset(options);
520
 
                        
 
520
 
521
521
                p_array_init(&act->recipients, pool, 4);
522
 
                
 
522
 
523
523
                raw_address = NULL;
524
524
                while ( (result=sieve_coded_stringlist_next_item(options, &raw_address))
525
525
                        && raw_address != NULL ) {
526
526
                        const char *error = NULL;
527
527
                        const char *addr_norm = sieve_address_normalize(raw_address, &error);
528
 
                        
 
528
 
529
529
                        /* Add if valid address */
530
530
                        if ( addr_norm != NULL ) {
531
531
                                const struct ext_notify_recipient *rcpts;
533
533
 
534
534
                                /* Prevent duplicates */
535
535
                                rcpts = array_get(&act->recipients, &rcpt_count);
536
 
                                
 
536
 
537
537
                                for ( i = 0; i < rcpt_count; i++ ) {
538
538
                                        if ( sieve_address_compare
539
539
                                                (rcpts[i].normalized, addr_norm, TRUE) == 0 )
540
540
                                                break;
541
541
                                }
542
 
        
 
542
 
543
543
                                /* Add only if unique */
544
544
                                if ( i != rcpt_count ) {
545
 
                                        sieve_runtime_warning(renv, 
 
545
                                        sieve_runtime_warning(renv,
546
546
                                                sieve_error_script_location(renv->script, source_line),
547
547
                                                "duplicate recipient '%s' specified in the :options argument of "
548
 
                                                "the deprecated notify command", 
 
548
                                                "the deprecated notify command",
549
549
                                                str_sanitize(str_c(raw_address), 128));
550
550
 
551
 
                                }       else if 
 
551
                                }       else if
552
552
                                        ( array_count(&act->recipients) >= EXT_NOTIFY_MAX_RECIPIENTS ) {
553
 
                                        sieve_runtime_warning(renv, 
 
553
                                        sieve_runtime_warning(renv,
554
554
                                                sieve_error_script_location(renv->script, source_line),
555
555
                                                "more than the maximum %u recipients are specified "
556
556
                                                "for the deprecated notify command; "
557
557
                                                "the rest is discarded", EXT_NOTIFY_MAX_RECIPIENTS);
558
558
                                        break;
559
559
 
560
 
                                } else {                                                
561
 
                                        struct ext_notify_recipient recipient;                  
 
560
                                } else {
 
561
                                        struct ext_notify_recipient recipient;
562
562
 
563
563
                                        recipient.full = p_strdup(pool, str_c(raw_address));
564
564
                                        recipient.normalized = p_strdup(pool, addr_norm);
565
 
                
 
565
 
566
566
                                        array_append(&act->recipients, &recipient, 1);
567
 
                                }               
 
567
                                }
568
568
                        } else {
569
 
                                sieve_runtime_error(renv, 
 
569
                                sieve_runtime_error(renv,
570
570
                                        sieve_error_script_location(renv->script, source_line),
571
571
                                        "specified :options address '%s' is invalid for "
572
 
                                        "the deprecated notify command: %s", 
 
572
                                        "the deprecated notify command: %s",
573
573
                                        str_sanitize(str_c(raw_address), 128), error);
574
574
                                return SIEVE_EXEC_FAILURE;
575
575
                        }
576
576
                }
577
 
                
 
577
 
578
578
                if ( !result ) {
579
579
                        sieve_runtime_trace_error(renv, "invalid options stringlist");
580
580
                        return SIEVE_EXEC_BIN_CORRUPT;
581
581
                }
582
 
                
 
582
 
583
583
                return ( sieve_result_add_action
584
 
                        (renv, this_ext, &act_notify_old, NULL, source_line, (void *) act, 0) 
 
584
                        (renv, this_ext, &act_notify_old, NULL, source_line, (void *) act, 0)
585
585
                                >= 0 );
586
586
        }
587
587
 
595
595
/* Runtime verification */
596
596
 
597
597
static int act_notify_check_duplicate
598
 
(const struct sieve_runtime_env *renv ATTR_UNUSED, 
 
598
(const struct sieve_runtime_env *renv ATTR_UNUSED,
599
599
        const struct sieve_action *act ATTR_UNUSED,
600
600
        const struct sieve_action *act_other ATTR_UNUSED)
601
601
{
604
604
        const struct ext_notify_recipient *old_rcpts;
605
605
        unsigned int new_count, old_count, i, j;
606
606
        unsigned int del_start = 0, del_len = 0;
607
 
                
 
607
 
608
608
        if ( act->context == NULL || act_other->context == NULL )
609
609
                return 0;
610
610
 
618
618
                for ( j = 0; j < old_count; j++ ) {
619
619
                        if ( sieve_address_compare
620
620
                                (new_rcpts[i].normalized, old_rcpts[j].normalized, TRUE) == 0 )
621
 
                                break;                          
 
621
                                break;
622
622
                }
623
623
 
624
624
                if ( j == old_count ) {
632
632
                                new_rcpts = array_get(&new_nact->recipients, &new_count);
633
633
                        }
634
634
 
635
 
                        del_len = 0;            
 
635
                        del_len = 0;
636
636
                } else {
637
637
                        /* Mark deletion */
638
638
                        if ( del_len == 0 )
643
643
 
644
644
        /* Perform pending deletion */
645
645
        if ( del_len > 0 ) {
646
 
                array_delete(&new_nact->recipients, del_start, del_len);                        
 
646
                array_delete(&new_nact->recipients, del_start, del_len);
647
647
        }
648
648
 
649
649
        return ( array_count(&new_nact->recipients) > 0 ? 0 : 1 );
650
650
}
651
651
 
652
652
/* Result printing */
653
 
 
 
653
 
654
654
static void act_notify_print
655
 
(const struct sieve_action *action,     const struct sieve_result_print_env *rpenv, 
656
 
        bool *keep ATTR_UNUSED) 
 
655
(const struct sieve_action *action,     const struct sieve_result_print_env *rpenv,
 
656
        bool *keep ATTR_UNUSED)
657
657
{
658
 
        const struct ext_notify_action *act = 
 
658
        const struct ext_notify_action *act =
659
659
                (const struct ext_notify_action *) action->context;
660
660
        const struct ext_notify_recipient *recipients;
661
661
        unsigned int count, i;
662
662
 
663
663
        sieve_result_action_printf
664
664
                ( rpenv, "send (depricated) notification with method 'mailto':");
665
 
        
 
665
 
666
666
        /* Print main method parameters */
667
667
 
668
668
        sieve_result_printf
710
710
}
711
711
 
712
712
static bool act_notify_send
713
 
(const struct sieve_action_exec_env *aenv, 
 
713
(const struct sieve_action_exec_env *aenv,
714
714
        const struct ext_notify_action *act)
715
 
 
715
{
716
716
        const struct sieve_message_data *msgdata = aenv->msgdata;
717
717
        const struct sieve_script_env *senv = aenv->scriptenv;
718
718
        const struct ext_notify_recipient *recipients;
724
724
        /* Get recipients */
725
725
        recipients = array_get(&act->recipients, &count);
726
726
        if ( count == 0  ) {
727
 
                sieve_result_warning(aenv, 
 
727
                sieve_result_warning(aenv,
728
728
                        "notify action specifies no recipients; action has no effect");
729
729
                return TRUE;
730
730
        }
731
731
 
732
732
        /* Just to be sure */
733
733
        if ( senv->smtp_open == NULL || senv->smtp_close == NULL ) {
734
 
                sieve_result_warning(aenv, 
 
734
                sieve_result_warning(aenv,
735
735
                        "notify action has no means to send mail");
736
736
                return TRUE;
737
737
        }
738
 
        
 
738
 
739
739
        /* Send message to all recipients */
740
740
        for ( i = 0; i < count; i++ ) {
741
741
 
742
742
                if ( msgdata->return_path != NULL )
743
 
                        smtp_handle = senv->smtp_open(recipients[i].normalized, 
 
743
                        smtp_handle = senv->smtp_open(recipients[i].normalized,
744
744
                                senv->postmaster_address, &f);
745
 
                else            
 
745
                else
746
746
                        smtp_handle = senv->smtp_open(recipients[i].normalized, NULL, &f);
747
747
 
748
748
                outmsgid = sieve_message_get_new_id(senv);
749
 
        
 
749
 
750
750
                rfc2822_header_field_write(f, "X-Sieve", SIEVE_IMPLEMENTATION);
751
751
                rfc2822_header_field_write(f, "Message-ID", outmsgid);
752
752
                rfc2822_header_field_write(f, "Date", message_date_create(ioloop_time));
768
768
                        break;
769
769
                }
770
770
 
771
 
                rfc2822_header_field_printf(f, "From", "%s", 
 
771
                rfc2822_header_field_printf(f, "From", "%s",
772
772
                        t_strdup_printf("Postmaster <%s>", senv->postmaster_address));
773
773
 
774
774
                rfc2822_header_field_printf(f, "To", "%s", recipients[i].full);
780
780
 
781
781
                if (contains_8bit(act->message)) {
782
782
                        rfc2822_header_field_write(f, "MIME-Version", "1.0");
783
 
                        rfc2822_header_field_write(f, 
 
783
                        rfc2822_header_field_write(f,
784
784
                                "Content-Type", "text/plain; charset=UTF-8");
785
785
                        rfc2822_header_field_write(f, "Content-Transfer-Encoding", "8bit");
786
786
                }
788
788
                /* Generate message body */
789
789
                fprintf(f, "\r\n");
790
790
                fprintf(f, "%s\r\n", act->message);
791
 
                        
 
791
 
792
792
                if ( senv->smtp_close(smtp_handle) ) {
793
 
                        sieve_result_log(aenv, 
794
 
                                "sent mail notification to <%s>", 
 
793
                        sieve_result_log(aenv,
 
794
                                "sent mail notification to <%s>",
795
795
                                str_sanitize(recipients[i].normalized, 80));
796
796
                } else {
797
797
                        sieve_result_error(aenv,
798
798
                                "failed to send mail notification to <%s> "
799
 
                                "(refer to system log for more information)", 
 
799
                                "(refer to system log for more information)",
800
800
                                str_sanitize(recipients[i].normalized, 80));
801
801
                }
802
802
        }
805
805
}
806
806
 
807
807
static bool act_notify_commit
808
 
(const struct sieve_action *action, const struct sieve_action_exec_env *aenv, 
 
808
(const struct sieve_action *action, const struct sieve_action_exec_env *aenv,
809
809
        void *tr_context ATTR_UNUSED, bool *keep ATTR_UNUSED)
810
810
{
811
 
        const struct ext_notify_action *act = 
 
811
        const struct ext_notify_action *act =
812
812
                (const struct ext_notify_action *) action->context;
813
813
        const struct sieve_message_data *msgdata = aenv->msgdata;
814
814
        const char *const *headers;
821
821
                /* Theoretically multiple headers could exist, so lets make sure */
822
822
                while ( *hdsp != NULL ) {
823
823
                        if ( strcasecmp(*hdsp, "no") != 0 ) {
824
 
                                sieve_result_log(aenv, 
825
 
                                        "not sending notification for auto-submitted message from <%s>", 
826
 
                                        str_sanitize(msgdata->return_path, 128));       
827
 
                                        return TRUE;                             
 
824
                                sieve_result_log(aenv,
 
825
                                        "not sending notification for auto-submitted message from <%s>",
 
826
                                        str_sanitize(msgdata->return_path, 128));
 
827
                                        return TRUE;
828
828
                        }
829
829
                        hdsp++;
830
830
                }