~ubuntu-dev/ubuntu/lucid/dovecot/lucid-201002101901

« back to all changes in this revision

Viewing changes to libsieve/src/lib-sieve/plugins/variables/cmd-set.c

  • Committer: Chuck Short
  • Date: 2010-01-21 20:21:25 UTC
  • mfrom: (4.1.11 squeeze)
  • Revision ID: zulcss@ubuntu.com-20100121202125-pme73o491kfwj5nc
* Merge from debian testing, remaining changes:
  + Add new binary pkg dovecot-postfix that integrates postfix and dovecot
    automatically: (LP: #164837)
  + debian/control:
    - add new binary with short description
    - set Architecture all for dovecot-postfix (LP: #329878)
  + debian/dovecot-postfix.postinst:
    - create initial certificate symlinks to snakeoil.
    - set up postfix with postconf to:
      - use Maildir/ as the default mailbox.
      - use dovecot as the sasl authentication server.
      - use dovecot LDA (deliver).
      - use tls for smtp{d} services.
    - fix certificates paths in postfix' main.cf
    - add reject_unauth_destination to postfix' recipient restrictions
    - add reject_unknown_sender_domain to postfix' sender restriction
    - rename configuration name on remove, delete on purge
    - restart dovecot after linking certificates
    - handle use case when postfix is unconfigurated
  + debian/dovecot-postfix.dirs: create backup directory for postfix's config
    configuration
  + restart postfix and dovecot.
  + debian/dovecot-postfix.postrm:
    - remove all dovecot related configuration from postfix.
    - restart postfix and dovecot.
  + debian/dovecot-common.init:
    - check if /etc/dovecot/dovecot-postfix.conf exists and use it
      as the configuration file if so.
  + debian/patches/warning-ubuntu-postfix.dpatch
    - add warning about dovecot-postfix.conf in dovecot default
      configuration file
  + debian/patches/dovecot-postfix.conf.diff:
    - Ubuntu server custom changes to the default dovecot configuration for
      better interfation with postfix.
    - enable sieve plugin.
    - Ubuntu server custom changes to the default dovecot configuration for
      better integration with postfix:
      - enable imap, pop3, imaps, pop3s and managesieve by default.
      - enable dovecot LDA (deliver).
      - enable SASL auth socket in postfix private directory
   + debian/rules:
     - copy, patch and install dovecot-postfix.conf in /etc/dovecot/.
     - build architecure independent packages too
   + 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/*.
   + Fast TearDown: Update the lsb init header to not stop in level 6.
   + Add ufw integration:
     - Created debian/dovecot-common.ufw.profile.
     - debian/rules: install profile.
     - debian/control: suggest ufw.
   + debian/{control,rules}: enable PIE hardening.
   + dovecot-imapd, dovecot-pop3: Replaces dovecot-common (<< 1:1.1). (LP: #254721)
   + debian/control: Update Vcs-* headers.
   + Add SMTP-AUTH support for Outlook (login auth mechanism)
* New upstream release.
* debian/patches/gold-fix.patch: Removed. Fixed upstream.
* Moved libexec to lib corrections in dovecot-managesieve.patch and
  dovecot-managesieve-dist.patch to dovecot-example.patch
* debian/patches/dovecot-mboxlocking.patch: Regenerated to avoid FTBFS
  when quilt isn't installed.
* debian/patches/quota-mountpoint.patch: Removed. Not needed anymore.
* debian/patches/dovecot-quota.patch: Removed. Quotas aren't properly
  enabled unless mail_plugins = quota imap_quota.
* debian/patches/gold-fix.patch: Fixed configure script to build even
  with binutils-gold or --no-add-needed linker flag (Closes: #554306)
* debian/dovecot-common.init: fixed LSB headers. Thanks to Pascal Volk.
  (Closes: #558040)
* debian/changelog: added CVE references to previous changelog entry.
* debian/rules: checked up the build system. It's not fragile anymore.
  (Closes: 493803)
* debian/dovecot-common.postinst: Now invoking dpkg-reconfigure
  on dovecot-common is enough to generate new certificates
  if the previous ones were removed. (Closes: #545582)
* debian/rules: No longer install convert-tool in /usr/bin.
  It isn't an user utility and it should stay in /usr/lib/dovecot
  like all other similar tool.
* New upstream release. (Closes: #557601)
* [SECURITY] Fixes local information disclosure and denial of service.
  (see: http://www.dovecot.org/list/dovecot-news/2009-November/000143.html
  and CVE-2009-3897)
* Added myself to uploaders.
* Switched to the new source format "3.0 (quilt)":
  - removed dpatch from build-depends
  - removed debian/README.source because now we use only standard
    dpkg features
  - regenerated all patches
* Prepared to switch to multi-origin source:
  - recreated dovecot-libsieve.patch and dovecot-managesieve-dist.patch
    starting from the upstream tarball
  - removed all autotools related build-depends and build-conflict
  - renamed dovecot-libsieve and dovecot-managesieve directories
    to libsieve and managesieve.
* debian/rules: Moved the configuration of libsieve and managesieve from
  the build phase to the configuration phase
* Added dovecot-dbg package  with debugging symbols.  Thanks Stephan Bosch.
  (Closes: #554710)
* Fixed some stray libexec'isms in the default configuration.
* New upstream release.
* debian/dovecot-common.init:
  - use $CONF when starting the daemon. (Closes: #549944)
  - always output start/stop messages. (Closes: #523810)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
 
2
 */
 
3
 
 
4
#include "lib.h"
 
5
#include "str.h"
 
6
#include "array.h"
 
7
 
 
8
#include "sieve-common.h"
 
9
#include "sieve-extensions.h"
 
10
 
 
11
#include "sieve-code.h"
 
12
#include "sieve-ast.h"
 
13
#include "sieve-commands.h"
 
14
#include "sieve-binary.h"
 
15
 
 
16
#include "sieve-validator.h"
 
17
#include "sieve-generator.h"
 
18
#include "sieve-interpreter.h"
 
19
#include "sieve-dump.h"
 
20
 
 
21
#include "ext-variables-common.h"
 
22
#include "ext-variables-modifiers.h"
 
23
 
 
24
/* 
 
25
 * Set command 
 
26
 *      
 
27
 * Syntax: 
 
28
 *    set [MODIFIER] <name: string> <value: string>
 
29
 */
 
30
 
 
31
static bool cmd_set_registered
 
32
        (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg);
 
33
static bool cmd_set_pre_validate
 
34
        (struct sieve_validator *validator, struct sieve_command_context *cmd);
 
35
static bool cmd_set_validate
 
36
        (struct sieve_validator *validator, struct sieve_command_context *cmd);
 
37
static bool cmd_set_generate
 
38
        (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx);
 
39
 
 
40
const struct sieve_command cmd_set = { 
 
41
        "set",
 
42
        SCT_COMMAND, 
 
43
        2, 0, FALSE, FALSE, 
 
44
        cmd_set_registered,
 
45
        cmd_set_pre_validate,  
 
46
        cmd_set_validate, 
 
47
        cmd_set_generate, 
 
48
        NULL 
 
49
};
 
50
 
 
51
/* 
 
52
 * Set operation 
 
53
 */
 
54
 
 
55
static bool cmd_set_operation_dump
 
56
        (const struct sieve_operation *op,      
 
57
                const struct sieve_dumptime_env *denv, sieve_size_t *address);
 
58
static int cmd_set_operation_execute
 
59
        (const struct sieve_operation *op, 
 
60
                const struct sieve_runtime_env *renv, sieve_size_t *address);
 
61
 
 
62
const struct sieve_operation cmd_set_operation = { 
 
63
        "SET",
 
64
        &variables_extension,
 
65
        EXT_VARIABLES_OPERATION_SET,
 
66
        cmd_set_operation_dump, 
 
67
        cmd_set_operation_execute
 
68
};
 
69
 
 
70
/* 
 
71
 * Compiler context 
 
72
 */
 
73
 
 
74
struct cmd_set_context {
 
75
        ARRAY_DEFINE(modifiers, const struct sieve_variables_modifier *);
 
76
};
 
77
 
 
78
/* 
 
79
 * Set modifier tag
 
80
 *
 
81
 * [MODIFIER]:
 
82
 *   ":lower" / ":upper" / ":lowerfirst" / ":upperfirst" /
 
83
 *             ":quotewildcard" / ":length"
 
84
 */
 
85
 
 
86
/* Forward declarations */
 
87
 
 
88
static bool tag_modifier_is_instance_of
 
89
        (struct sieve_validator *validator, struct sieve_command_context *cmdctx,       
 
90
                struct sieve_ast_argument *arg);        
 
91
static bool tag_modifier_validate
 
92
        (struct sieve_validator *validator, struct sieve_ast_argument **arg, 
 
93
                struct sieve_command_context *cmd);
 
94
 
 
95
/* Modifier tag object */
 
96
 
 
97
const struct sieve_argument modifier_tag = { 
 
98
        "MODIFIER",
 
99
        tag_modifier_is_instance_of, 
 
100
        NULL,
 
101
        tag_modifier_validate, 
 
102
        NULL, NULL
 
103
};
 
104
 
 
105
/* Modifier tag implementation */ 
 
106
 
 
107
static bool tag_modifier_is_instance_of
 
108
(struct sieve_validator *validator ATTR_UNUSED, 
 
109
        struct sieve_command_context *cmdctx ATTR_UNUSED,       
 
110
        struct sieve_ast_argument *arg)
 
111
{       
 
112
        const struct sieve_variables_modifier *modf = ext_variables_modifier_find
 
113
                (validator, sieve_ast_argument_tag(arg));
 
114
 
 
115
        arg->context = (void *) modf;
 
116
                
 
117
        return ( modf != NULL );
 
118
}
 
119
 
 
120
static bool tag_modifier_validate
 
121
(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
 
122
        struct sieve_command_context *cmd)
 
123
{
 
124
        unsigned int i;
 
125
        bool inserted;
 
126
        const struct sieve_variables_modifier *modf = 
 
127
                (const struct sieve_variables_modifier *) (*arg)->context;
 
128
        struct cmd_set_context *sctx = (struct cmd_set_context *) cmd->data;
 
129
        
 
130
        inserted = FALSE;
 
131
        for ( i = 0; i < array_count(&sctx->modifiers) && !inserted; i++ ) {
 
132
                const struct sieve_variables_modifier * const *smdf =
 
133
                        array_idx(&sctx->modifiers, i);
 
134
        
 
135
                if ( (*smdf)->precedence == modf->precedence ) {
 
136
                        sieve_argument_validate_error(validator, *arg, 
 
137
                                "modifiers :%s and :%s specified for the set command conflict "
 
138
                                "having equal precedence", 
 
139
                                (*smdf)->object.identifier, modf->object.identifier);
 
140
                        return FALSE;
 
141
                }
 
142
                        
 
143
                if ( (*smdf)->precedence < modf->precedence ) {
 
144
                        array_insert(&sctx->modifiers, i, &modf, 1);
 
145
                        inserted = TRUE;
 
146
                }
 
147
        }
 
148
        
 
149
        if ( !inserted )
 
150
                array_append(&sctx->modifiers, &modf, 1);
 
151
        
 
152
        /* Added to modifier list; self-destruct to prevent duplicate generation */
 
153
        *arg = sieve_ast_arguments_detach(*arg, 1);
 
154
        
 
155
        return TRUE;
 
156
}
 
157
 
 
158
/* Command registration */
 
159
 
 
160
static bool cmd_set_registered
 
161
        (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) 
 
162
{
 
163
        sieve_validator_register_tag(validator, cmd_reg, &modifier_tag, 0);     
 
164
 
 
165
        return TRUE;
 
166
}
 
167
 
 
168
/* 
 
169
 * Command validation 
 
170
 */
 
171
 
 
172
static bool cmd_set_pre_validate
 
173
(struct sieve_validator *validator ATTR_UNUSED, 
 
174
        struct sieve_command_context *cmd)
 
175
{
 
176
        pool_t pool = sieve_command_pool(cmd);
 
177
        struct cmd_set_context *sctx = p_new(pool, struct cmd_set_context, 1);
 
178
        
 
179
        /* Create an array for the sorted list of modifiers */
 
180
        p_array_init(&sctx->modifiers, pool, 2);
 
181
 
 
182
        cmd->data = (void *) sctx;
 
183
        
 
184
        return TRUE;
 
185
 
186
 
 
187
static bool cmd_set_validate(struct sieve_validator *validator, 
 
188
        struct sieve_command_context *cmd) 
 
189
 
190
        struct sieve_ast_argument *arg = cmd->first_positional;
 
191
                
 
192
        if ( !sieve_validate_positional_argument
 
193
                (validator, cmd, arg, "name", 1, SAAT_STRING) ) {
 
194
                return FALSE;
 
195
        }
 
196
        
 
197
        if ( !sieve_variable_argument_activate(validator, cmd, arg, TRUE) ) {
 
198
                return FALSE;
 
199
        }
 
200
 
 
201
        arg = sieve_ast_argument_next(arg);
 
202
        
 
203
        if ( !sieve_validate_positional_argument
 
204
                (validator, cmd, arg, "value", 2, SAAT_STRING) ) {
 
205
                return FALSE;
 
206
        }
 
207
        
 
208
        return sieve_validator_argument_activate(validator, cmd, arg, FALSE);   
 
209
}
 
210
 
 
211
/*
 
212
 * Code generation
 
213
 */
 
214
 
 
215
static bool cmd_set_generate
 
216
        (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) 
 
217
{
 
218
        struct sieve_binary *sbin = cgenv->sbin;
 
219
        struct cmd_set_context *sctx = (struct cmd_set_context *) ctx->data;
 
220
        unsigned int i; 
 
221
 
 
222
        sieve_operation_emit_code(sbin, &cmd_set_operation); 
 
223
 
 
224
        /* Generate arguments */
 
225
        if ( !sieve_generate_arguments(cgenv, ctx, NULL) )
 
226
                return FALSE;   
 
227
                
 
228
        /* Generate modifiers (already sorted during validation) */
 
229
        sieve_binary_emit_byte(sbin, array_count(&sctx->modifiers));
 
230
        for ( i = 0; i < array_count(&sctx->modifiers); i++ ) {
 
231
                const struct sieve_variables_modifier * const * modf =
 
232
                        array_idx(&sctx->modifiers, i);
 
233
                        
 
234
                ext_variables_opr_modifier_emit(sbin, *modf);
 
235
        }
 
236
 
 
237
        return TRUE;
 
238
}
 
239
 
 
240
/* 
 
241
 * Code dump
 
242
 */
 
243
 
 
244
static bool cmd_set_operation_dump
 
245
(const struct sieve_operation *op ATTR_UNUSED,
 
246
        const struct sieve_dumptime_env *denv, sieve_size_t *address)
 
247
{       
 
248
        unsigned int mdfs, i;
 
249
        
 
250
        sieve_code_dumpf(denv, "SET");
 
251
        sieve_code_descend(denv);
 
252
        
 
253
        /* Print both variable name and string value */
 
254
        if ( !sieve_opr_string_dump(denv, address, "variable") ||
 
255
                !sieve_opr_string_dump(denv, address, "value") )
 
256
                return FALSE;
 
257
        
 
258
        /* Read the number of applied modifiers we need to read */
 
259
        if ( !sieve_binary_read_byte(denv->sbin, address, &mdfs) ) 
 
260
                return FALSE;
 
261
        
 
262
        /* Print all modifiers (sorted during code generation already) */
 
263
        for ( i = 0; i < mdfs; i++ ) {
 
264
                if ( !ext_variables_opr_modifier_dump(denv, address) )
 
265
                        return FALSE;
 
266
        }
 
267
        
 
268
        return TRUE;
 
269
}
 
270
 
 
271
/* 
 
272
 * Code execution
 
273
 */
 
274
 
 
275
static int cmd_set_operation_execute
 
276
(const struct sieve_operation *op ATTR_UNUSED,
 
277
        const struct sieve_runtime_env *renv, sieve_size_t *address)
 
278
{       
 
279
        struct sieve_variable_storage *storage;
 
280
        unsigned int var_index, mdfs, i;
 
281
        string_t *value;
 
282
        int ret = SIEVE_EXEC_OK;
 
283
 
 
284
        /*
 
285
         * Read the normal operands
 
286
         */
 
287
                
 
288
        /* Read the variable */
 
289
        if ( !sieve_variable_operand_read
 
290
                (renv, address, &storage, &var_index) ) {
 
291
                sieve_runtime_trace_error(renv, "invalid variable operand");
 
292
                return SIEVE_EXEC_BIN_CORRUPT;
 
293
        }
 
294
                
 
295
        /* Read the raw string value */
 
296
        if ( !sieve_opr_string_read(renv, address, &value) ) {
 
297
                sieve_runtime_trace_error(renv, "invalid string operand");
 
298
                return SIEVE_EXEC_BIN_CORRUPT;
 
299
        }
 
300
                
 
301
        /* Read the number of modifiers used */
 
302
        if ( !sieve_binary_read_byte(renv->sbin, address, &mdfs) ) {
 
303
                sieve_runtime_trace_error(renv, "invalid modifier count");
 
304
                return SIEVE_EXEC_BIN_CORRUPT;
 
305
        }
 
306
        
 
307
        /* 
 
308
         * Determine and assign the value 
 
309
         */
 
310
 
 
311
        sieve_runtime_trace(renv, "SET action");
 
312
 
 
313
        /* Hold value within limits */
 
314
        if ( str_len(value) > SIEVE_VARIABLES_MAX_VARIABLE_SIZE )
 
315
                str_truncate(value, SIEVE_VARIABLES_MAX_VARIABLE_SIZE);
 
316
 
 
317
        T_BEGIN {
 
318
                /* Apply modifiers if necessary (sorted during code generation already) */
 
319
                if ( str_len(value) > 0 ) {
 
320
                        for ( i = 0; i < mdfs; i++ ) {
 
321
                                string_t *new_value;
 
322
                                const struct sieve_variables_modifier *modf =
 
323
                                        ext_variables_opr_modifier_read(renv, address);
 
324
 
 
325
                                if ( modf == NULL ) {
 
326
                                        value = NULL;
 
327
 
 
328
                                        sieve_runtime_trace_error(renv, "invalid modifier operand");
 
329
                                        ret = SIEVE_EXEC_BIN_CORRUPT;
 
330
                                        break;
 
331
                                }
 
332
                                
 
333
                                if ( modf->modify != NULL ) {
 
334
                                        if ( !modf->modify(value, &new_value) ) {
 
335
                                                value = NULL;
 
336
                                                ret = SIEVE_EXEC_FAILURE;
 
337
                                                break;
 
338
                                        }
 
339
 
 
340
                                        value = new_value;
 
341
                                        if ( value == NULL )
 
342
                                                break;
 
343
 
 
344
                                        /* Hold value within limits */
 
345
                                        if ( str_len(value) > SIEVE_VARIABLES_MAX_VARIABLE_SIZE )
 
346
                                                str_truncate(value, SIEVE_VARIABLES_MAX_VARIABLE_SIZE);
 
347
                                }
 
348
                        }
 
349
                }       
 
350
                
 
351
                /* Actually assign the value if all is well */
 
352
                if ( value != NULL ) {
 
353
                        if ( !sieve_variable_assign(storage, var_index, value) )
 
354
                                ret = SIEVE_EXEC_BIN_CORRUPT;
 
355
                }       
 
356
        } T_END;
 
357
                        
 
358
        if ( ret <= 0 ) 
 
359
                return ret;             
 
360
 
 
361
        return ( value != NULL );
 
362
}
 
363
 
 
364
 
 
365
 
 
366
 
 
367
 
 
368