~ubuntu-branches/ubuntu/utopic/dovecot/utopic-proposed

« back to all changes in this revision

Viewing changes to pigeonhole/src/lib-sieve/sieve-interpreter.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (4.1.35 sid)
  • Revision ID: package-import@ubuntu.com-20140108093549-i72o93pux8p0dlaf
Tags: 1:2.2.9-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2002-2012 Pigeonhole authors, see the included COPYING file
 
1
/* Copyright (c) 2002-2013 Pigeonhole authors, see the included COPYING file
2
2
 */
3
3
 
4
4
#include "lib.h"
26
26
 
27
27
#include <string.h>
28
28
 
29
 
/* 
30
 
 * Interpreter extension 
 
29
/*
 
30
 * Interpreter extension
31
31
 */
32
32
 
33
33
struct sieve_interpreter_extension_reg {
37
37
        void *context;
38
38
};
39
39
 
40
 
/* 
41
 
 * Interpreter 
 
40
/*
 
41
 * Interpreter
42
42
 */
43
43
 
44
44
struct sieve_interpreter {
45
45
        pool_t pool;
46
46
 
47
47
        /* Runtime data for extensions */
48
 
        ARRAY_DEFINE(extensions, struct sieve_interpreter_extension_reg); 
49
 
        
50
 
        sieve_size_t reset_vector;      
51
 
                
 
48
        ARRAY(struct sieve_interpreter_extension_reg) extensions;
 
49
 
 
50
        sieve_size_t reset_vector;
 
51
 
52
52
        /* Execution status */
53
 
        
 
53
 
54
54
        sieve_size_t pc;          /* Program counter */
55
55
        bool interrupted;         /* Interpreter interrupt requested */
56
56
        bool test_result;         /* Result of previous test command */
57
 
        
 
57
 
58
58
        /* Runtime environment */
59
59
        struct sieve_runtime_env runenv;
60
60
        struct sieve_runtime_trace trace;
61
61
 
62
62
        /* Current operation */
63
 
        struct sieve_operation oprtn; 
 
63
        struct sieve_operation oprtn;
64
64
 
65
65
        /* Location information */
66
66
        struct sieve_binary_debug_reader *dreader;
68
68
};
69
69
 
70
70
static struct sieve_interpreter *_sieve_interpreter_create
71
 
(struct sieve_binary *sbin, struct sieve_binary_block *sblock, 
 
71
(struct sieve_binary *sbin, struct sieve_binary_block *sblock,
72
72
        struct sieve_script *script, const struct sieve_message_data *msgdata,
73
73
        const struct sieve_script_env *senv, struct sieve_error_handler *ehandler,
74
 
        enum sieve_runtime_flags flags) 
 
74
        enum sieve_runtime_flags flags)
75
75
{
76
76
        unsigned int i, ext_count;
77
77
        struct sieve_interpreter *interp;
81
81
        unsigned int debug_block_id;
82
82
        sieve_size_t *address;
83
83
        bool success = TRUE;
84
 
        
85
 
        pool = pool_alloconly_create("sieve_interpreter", 4096);        
 
84
 
 
85
        pool = pool_alloconly_create("sieve_interpreter", 4096);
86
86
        interp = p_new(pool, struct sieve_interpreter, 1);
87
87
        interp->pool = pool;
88
88
 
109
109
                interp->runenv.trace = &interp->trace;
110
110
        }
111
111
 
112
 
        if ( senv->exec_status == NULL ) 
 
112
        if ( senv->exec_status == NULL )
113
113
                interp->runenv.exec_status = p_new(interp->pool, struct sieve_exec_status, 1);
114
114
        else
115
115
                interp->runenv.exec_status = senv->exec_status;
116
116
 
117
 
        if ( script == NULL )   
 
117
        if ( script == NULL )
118
118
                interp->runenv.script = sieve_binary_script(sbin);
119
119
        else
120
120
                interp->runenv.script = script;
121
 
        
 
121
 
122
122
        interp->runenv.pc = 0;
123
123
        address = &(interp->runenv.pc);
124
124
 
127
127
        p_array_init(&interp->extensions, pool, sieve_extensions_get_count(svinst));
128
128
 
129
129
        /* Pre-load core language features implemented as 'extensions' */
130
 
        ext_preloaded = sieve_extensions_get_preloaded(svinst, &ext_count); 
 
130
        ext_preloaded = sieve_extensions_get_preloaded(svinst, &ext_count);
131
131
        for ( i = 0; i < ext_count; i++ ) {
132
132
                const struct sieve_extension_def *ext_def = ext_preloaded[i]->def;
133
133
 
134
134
                if ( ext_def != NULL && ext_def->interpreter_load != NULL )
135
135
                        (void)ext_def->interpreter_load
136
 
                                (ext_preloaded[i], &interp->runenv, address);           
 
136
                                (ext_preloaded[i], &interp->runenv, address);
137
137
        }
138
138
 
139
139
        /* Load debug block */
151
151
        }
152
152
 
153
153
        /* Load other extensions listed in code */
154
 
        if ( success && 
 
154
        if ( success &&
155
155
                sieve_binary_read_unsigned(sblock, address, &ext_count) ) {
156
156
 
157
157
                for ( i = 0; i < ext_count; i++ ) {
158
158
                        unsigned int code = 0;
159
159
                        const struct sieve_extension *ext;
160
 
                        
 
160
 
161
161
                        if ( !sieve_binary_read_extension(sblock, address, &code, &ext) ) {
162
162
                                success = FALSE;
163
163
                                break;
164
164
                        }
165
 
 
 
165
 
166
166
                        if ( ext->def != NULL ) {
167
167
                                if ( ext->global && (flags & SIEVE_RUNTIME_FLAG_NOGLOBAL) != 0 ) {
168
168
                                        sieve_runtime_error(&interp->runenv, NULL,
173
173
                                        break;
174
174
                                }
175
175
 
176
 
                                if ( ext->def->interpreter_load != NULL && 
 
176
                                if ( ext->def->interpreter_load != NULL &&
177
177
                                        !ext->def->interpreter_load(ext, &interp->runenv, address) ) {
178
178
                                        success = FALSE;
179
179
                                        break;
182
182
                }
183
183
        }       else
184
184
                success = FALSE;
185
 
        
 
185
 
186
186
        if ( !success ) {
187
187
                sieve_interpreter_free(&interp);
188
188
                interp = NULL;
189
189
        } else {
190
190
                interp->reset_vector = *address;
191
191
        }
192
 
        
 
192
 
193
193
        return interp;
194
194
}
195
195
 
196
196
struct sieve_interpreter *sieve_interpreter_create
197
197
(struct sieve_binary *sbin, const struct sieve_message_data *msgdata,
198
198
        const struct sieve_script_env *senv, struct sieve_error_handler *ehandler,
199
 
        enum sieve_runtime_flags flags) 
 
199
        enum sieve_runtime_flags flags)
200
200
{
201
201
        struct sieve_binary_block *sblock;
202
202
 
203
 
        if ( (sblock=sieve_binary_block_get(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM)) 
 
203
        if ( (sblock=sieve_binary_block_get(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM))
204
204
                == NULL )
205
205
                return NULL;
206
206
 
210
210
 
211
211
struct sieve_interpreter *sieve_interpreter_create_for_block
212
212
(struct sieve_binary_block *sblock, struct sieve_script *script,
213
 
        const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, 
214
 
        struct sieve_error_handler *ehandler, enum sieve_runtime_flags flags) 
 
213
        const struct sieve_message_data *msgdata, const struct sieve_script_env *senv,
 
214
        struct sieve_error_handler *ehandler, enum sieve_runtime_flags flags)
215
215
{
216
216
        if ( sblock == NULL ) return NULL;
217
217
 
220
220
                        ehandler, flags);
221
221
}
222
222
 
223
 
void sieve_interpreter_free(struct sieve_interpreter **interp) 
 
223
void sieve_interpreter_free(struct sieve_interpreter **interp)
224
224
{
225
225
        const struct sieve_interpreter_extension_reg *eregs;
226
226
        unsigned int ext_count, i;
238
238
        sieve_binary_unref(&(*interp)->runenv.sbin);
239
239
        sieve_error_handler_unref(&(*interp)->runenv.ehandler);
240
240
 
241
 
        pool_unref(&((*interp)->pool)); 
 
241
        pool_unref(&((*interp)->pool));
242
242
        *interp = NULL;
243
243
}
244
244
 
293
293
                if ( location == NULL )
294
294
                        location = sieve_runtime_get_full_command_location(renv);
295
295
 
296
 
                msg_func(renv->ehandler, location, fmt, args); 
 
296
                msg_func(renv->ehandler, location, fmt, args);
297
297
        } T_END;
298
298
}
299
299
 
343
343
                        location = sieve_runtime_get_full_command_location(renv);
344
344
 
345
345
                sieve_vcritical
346
 
                        (renv->svinst, renv->ehandler, location, user_prefix, fmt, args); 
 
346
                        (renv->svinst, renv->ehandler, location, user_prefix, fmt, args);
347
347
        } T_END;
348
348
 
349
349
        va_end(args);
403
403
 
404
404
        if ( ext->id < 0 ) return;
405
405
 
406
 
        reg = array_idx_modifiable(&interp->extensions, (unsigned int) ext->id);        
 
406
        reg = array_idx_modifiable(&interp->extensions, (unsigned int) ext->id);
407
407
        reg->intext = intext;
408
408
        reg->ext = ext;
409
409
        reg->context = context;
410
410
}
411
411
 
412
412
void sieve_interpreter_extension_set_context
413
 
(struct sieve_interpreter *interp, const struct sieve_extension *ext, 
 
413
(struct sieve_interpreter *interp, const struct sieve_extension *ext,
414
414
        void *context)
415
415
{
416
416
        struct sieve_interpreter_extension_reg *reg;
417
417
 
418
418
        if ( ext->id < 0 ) return;
419
 
        
420
 
        reg = array_idx_modifiable(&interp->extensions, (unsigned int) ext->id);        
 
419
 
 
420
        reg = array_idx_modifiable(&interp->extensions, (unsigned int) ext->id);
421
421
        reg->context = context;
422
422
}
423
423
 
424
424
void *sieve_interpreter_extension_get_context
425
 
(struct sieve_interpreter *interp, const struct sieve_extension *ext) 
 
425
(struct sieve_interpreter *interp, const struct sieve_extension *ext)
426
426
{
427
427
        const struct sieve_interpreter_extension_reg *reg;
428
428
 
429
429
        if  ( ext->id < 0 || ext->id >= (int) array_count(&interp->extensions) )
430
430
                return NULL;
431
 
        
432
 
        reg = array_idx(&interp->extensions, (unsigned int) ext->id);           
 
431
 
 
432
        reg = array_idx(&interp->extensions, (unsigned int) ext->id);
433
433
 
434
434
        return reg->context;
435
435
}
436
436
 
437
 
/* 
438
 
 * Program flow 
 
437
/*
 
438
 * Program flow
439
439
 */
440
440
 
441
 
void sieve_interpreter_reset(struct sieve_interpreter *interp) 
 
441
void sieve_interpreter_reset(struct sieve_interpreter *interp)
442
442
{
443
443
        interp->runenv.pc = interp->reset_vector;
444
444
        interp->interrupted = FALSE;
463
463
        sieve_size_t *address = &(interp->runenv.pc);
464
464
        sieve_size_t jmp_start = *address;
465
465
        sieve_offset_t jmp_offset;
466
 
        
 
466
 
467
467
        if ( !sieve_binary_read_offset(renv->sblock, address, &jmp_offset) )
468
468
        {
469
 
                sieve_runtime_trace_error(renv, "invalid jump offset"); 
 
469
                sieve_runtime_trace_error(renv, "invalid jump offset");
470
470
                return SIEVE_EXEC_BIN_CORRUPT;
471
471
        }
472
472
 
473
 
        if ( jmp_start + jmp_offset <= sieve_binary_block_get_size(renv->sblock) && 
474
 
                jmp_start + jmp_offset > 0 ) 
475
 
        {       
 
473
        if ( jmp_start + jmp_offset <= sieve_binary_block_get_size(renv->sblock) &&
 
474
                jmp_start + jmp_offset > 0 )
 
475
        {
476
476
                if ( jump ) {
477
477
                        sieve_size_t jmp_addr = jmp_start + jmp_offset;
478
478
 
479
479
                        if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
480
 
                                unsigned int jmp_line = 
 
480
                                unsigned int jmp_line =
481
481
                                        sieve_runtime_get_source_location(renv, jmp_addr);
482
482
 
483
483
                                if ( sieve_runtime_trace_hasflag(renv, SIEVE_TRFLG_ADDRESSES) ) {
484
 
                                        sieve_runtime_trace(renv, 0, "jumping to line %d [%08llx]", 
 
484
                                        sieve_runtime_trace(renv, 0, "jumping to line %d [%08llx]",
485
485
                                                jmp_line, (long long unsigned int) jmp_addr);
486
486
                                } else {
487
487
                                        sieve_runtime_trace(renv, 0, "jumping to line %d", jmp_line);
490
490
 
491
491
                        *address = jmp_addr;
492
492
                } else {
493
 
                        sieve_runtime_trace(renv, 0, "not jumping");    
 
493
                        sieve_runtime_trace(renv, 0, "not jumping");
494
494
                }
495
 
                
 
495
 
496
496
                return SIEVE_EXEC_OK;
497
497
        }
498
 
        
 
498
 
499
499
        sieve_runtime_trace_error(renv, "jump offset out of range");
500
500
        return SIEVE_EXEC_BIN_CORRUPT;
501
501
}
516
516
        return interp->test_result;
517
517
}
518
518
 
519
 
/* 
520
 
 * Code execute 
 
519
/*
 
520
 * Code execute
521
521
 */
522
522
 
523
523
static int sieve_interpreter_operation_execute
524
 
(struct sieve_interpreter *interp) 
 
524
(struct sieve_interpreter *interp)
525
525
{
526
526
        struct sieve_operation *oprtn = &(interp->oprtn);
527
527
        sieve_size_t *address = &(interp->runenv.pc);
543
543
                        } T_END;
544
544
                } else {
545
545
                        sieve_runtime_trace
546
 
                                (&interp->runenv, SIEVE_TRLVL_COMMANDS, "OP: %s (NOOP)", 
 
546
                                (&interp->runenv, SIEVE_TRLVL_COMMANDS, "OP: %s (NOOP)",
547
547
                                        sieve_operation_mnemonic(oprtn));
548
548
                }
549
549
 
550
550
                return result;
551
551
        }
552
 
        
 
552
 
553
553
        /* Binary corrupt */
554
 
        sieve_runtime_trace_error(&interp->runenv, "Encountered invalid operation");    
 
554
        sieve_runtime_trace_error(&interp->runenv, "Encountered invalid operation");
555
555
        return SIEVE_EXEC_BIN_CORRUPT;
556
 
}               
 
556
}
557
557
 
558
558
int sieve_interpreter_continue
559
 
(struct sieve_interpreter *interp, bool *interrupted) 
 
559
(struct sieve_interpreter *interp, bool *interrupted)
560
560
{
561
561
        sieve_size_t *address = &(interp->runenv.pc);
562
562
        int ret = SIEVE_EXEC_OK;
563
 
        
 
563
 
564
564
        sieve_result_ref(interp->runenv.result);
565
565
        interp->interrupted = FALSE;
566
 
        
 
566
 
567
567
        if ( interrupted != NULL )
568
568
                *interrupted = FALSE;
569
 
        
570
 
        while ( ret == SIEVE_EXEC_OK && !interp->interrupted && 
 
569
 
 
570
        while ( ret == SIEVE_EXEC_OK && !interp->interrupted &&
571
571
                *address < sieve_binary_block_get_size(interp->runenv.sblock) ) {
572
 
                
 
572
 
573
573
                ret = sieve_interpreter_operation_execute(interp);
574
574
 
575
575
                if ( ret != SIEVE_EXEC_OK ) {
576
 
                        sieve_runtime_trace(&interp->runenv, SIEVE_TRLVL_NONE, 
 
576
                        sieve_runtime_trace(&interp->runenv, SIEVE_TRLVL_NONE,
577
577
                                "[[EXECUTION ABORTED]]");
578
578
                }
579
579
        }
580
 
        
 
580
 
581
581
        if ( interrupted != NULL )
582
582
                *interrupted = interp->interrupted;
583
 
                        
 
583
 
584
584
        sieve_result_unref(&interp->runenv.result);
585
585
        return ret;
586
586
}
587
587
 
588
588
int sieve_interpreter_start
589
 
(struct sieve_interpreter *interp, struct sieve_result *result, bool *interrupted) 
 
589
(struct sieve_interpreter *interp, struct sieve_result *result, bool *interrupted)
590
590
{
591
591
        const struct sieve_interpreter_extension_reg *eregs;
592
592
        unsigned int ext_count, i;
593
 
        
 
593
 
594
594
        interp->runenv.result = result;
595
 
        interp->runenv.msgctx = sieve_result_get_message_context(result);               
596
 
        
 
595
        interp->runenv.msgctx = sieve_result_get_message_context(result);
 
596
 
597
597
        /* Signal registered extensions that the interpreter is being run */
598
598
        eregs = array_get(&interp->extensions, &ext_count);
599
599
        for ( i = 0; i < ext_count; i++ ) {
601
601
                        eregs[i].intext->run(eregs[i].ext, &interp->runenv, eregs[i].context);
602
602
        }
603
603
 
604
 
        return sieve_interpreter_continue(interp, interrupted); 
 
604
        return sieve_interpreter_continue(interp, interrupted);
605
605
}
606
606
 
607
607
int sieve_interpreter_run
608
608
(struct sieve_interpreter *interp, struct sieve_result *result)
609
609
{
610
610
        int ret = 0;
611
 
        
 
611
 
612
612
        sieve_interpreter_reset(interp);
613
613
        sieve_result_ref(result);
614
 
        
 
614
 
615
615
        ret = sieve_interpreter_start(interp, result, NULL);
616
 
        
 
616
 
617
617
        sieve_result_unref(&result);
618
 
        
 
618
 
619
619
        return ret;
620
620
}
621
621