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

« back to all changes in this revision

Viewing changes to sieve/src/lib-sieve/mcht-matches.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:
1
 
/* Copyright (c) 2002-2010 Dovecot Sieve authors, see the included COPYING file 
 
1
/* Copyright (c) 2002-2010 Dovecot Sieve authors, see the included COPYING file
2
2
 */
3
 
 
4
 
/* Match-type ':matches' 
 
3
 
 
4
/* Match-type ':matches'
5
5
 */
6
6
 
7
7
#include "lib.h"
19
19
 */
20
20
 
21
21
static int mcht_matches_match
22
 
        (struct sieve_match_context *mctx, const char *val, size_t val_size, 
 
22
        (struct sieve_match_context *mctx, const char *val, size_t val_size,
23
23
                const char *key, size_t key_size, int key_index);
24
24
 
25
25
/*
30
30
        SIEVE_OBJECT("matches", &match_type_operand, SIEVE_MATCH_TYPE_MATCHES),
31
31
        TRUE, FALSE,
32
32
        NULL,
33
 
        sieve_match_substring_validate_context, 
 
33
        sieve_match_substring_validate_context,
34
34
        NULL,
35
35
        mcht_matches_match,
36
36
        NULL
45
45
#ifdef MATCH_DEBUG
46
46
#define debug_printf(...) printf ("match debug: " __VA_ARGS__)
47
47
#else
48
 
#define debug_printf(...) 
 
48
#define debug_printf(...)
49
49
#endif
50
50
 
51
51
/* FIXME: Naive implementation, substitute this with dovecot src/lib/str-find.c
52
52
 */
53
 
static inline bool _string_find(const struct sieve_comparator *cmp, 
 
53
static inline bool _string_find(const struct sieve_comparator *cmp,
54
54
        const char **valp, const char *vend, const char **keyp, const char *kend)
55
55
{
56
56
        while ( (*valp < vend) && (*keyp < kend) ) {
57
57
                if ( !cmp->def->char_match(cmp, valp, vend, keyp, kend) )
58
58
                        (*valp)++;
59
59
        }
60
 
        
 
60
 
61
61
        return (*keyp == kend);
62
62
}
63
63
 
64
64
static char _scan_key_section
65
65
        (string_t *section, const char **wcardp, const char *key_end)
66
66
{
67
 
        /* Find next wildcard and resolve escape sequences */   
 
67
        /* Find next wildcard and resolve escape sequences */
68
68
        str_truncate(section, 0);
69
69
        while ( *wcardp < key_end && **wcardp != '*' && **wcardp != '?') {
70
70
                if ( **wcardp == '\\' ) {
73
73
                str_append_c(section, **wcardp);
74
74
                (*wcardp)++;
75
75
        }
76
 
        
 
76
 
77
77
        /* Record wildcard character or \0 */
78
 
        if ( *wcardp < key_end ) {                      
 
78
        if ( *wcardp < key_end ) {
79
79
                return **wcardp;
80
 
        } 
81
 
        
 
80
        }
 
81
 
82
82
        i_assert( *wcardp == key_end );
83
83
        return '\0';
84
84
}
85
85
 
86
86
static int mcht_matches_match
87
 
(struct sieve_match_context *mctx, const char *val, size_t val_size, 
 
87
(struct sieve_match_context *mctx, const char *val, size_t val_size,
88
88
        const char *key, size_t key_size, int key_index ATTR_UNUSED)
89
89
{
90
90
        const struct sieve_comparator *cmp = mctx->comparator;
105
105
                val = "";
106
106
                val_size = 0;
107
107
        }
108
 
        
 
108
 
109
109
        /* Key sections */
110
110
        section = t_str_new(32);    /* Section (after beginning or *) */
111
111
        subsection = t_str_new(32); /* Sub-section (after ?) */
112
 
        
 
112
 
113
113
        /* Mark end of value and key */
114
114
        vend = (const char *) val + val_size;
115
115
        kend = (const char *) key + key_size;
128
128
                mvalue = t_str_new(32);     /* Match value (*) */
129
129
                mchars = t_str_new(32);     /* Match characters (.?..?.??) */
130
130
        }
131
 
        
132
 
        /* Match the pattern: 
 
131
 
 
132
        /* Match the pattern:
133
133
         *   <pattern> = <section>*<section>*<section>...
134
134
         *   <section> = <sub-section>?<sub-section>?<sub-section>...
135
135
         *
136
 
         * Escape sequences \? and \* need special attention. 
 
136
         * Escape sequences \? and \* need special attention.
137
137
         */
138
 
         
 
138
 
139
139
        debug_printf("=== Start ===\n");
140
140
        debug_printf("  key:   %s\n", t_strdup_until(key, kend));
141
141
        debug_printf("  value: %s\n", t_strdup_until(val, vend));
143
143
        /* Loop until either key or value ends */
144
144
        while (kp < kend && vp < vend ) {
145
145
                const char *needle, *nend;
146
 
                
 
146
 
147
147
                if ( !backtrack ) {
148
148
                        /* Search the next '*' wildcard in the key string */
149
149
 
150
150
                        wcard = next_wcard;
151
 
                        
152
 
                        /* Find the needle to look for in the string */ 
153
 
                        key_offset = 0; 
 
151
 
 
152
                        /* Find the needle to look for in the string */
 
153
                        key_offset = 0;
154
154
                        for (;;) {
155
155
                                next_wcard = _scan_key_section(section, &wp, kend);
156
 
                                
157
 
                                if ( wcard == '\0' || str_len(section) > 0 ) 
 
156
 
 
157
                                if ( wcard == '\0' || str_len(section) > 0 )
158
158
                                        break;
159
 
                                        
160
 
                                if ( next_wcard == '*' ) {      
 
159
 
 
160
                                if ( next_wcard == '*' ) {
161
161
                                        break;
162
162
                                }
163
 
                                        
164
 
                                if ( wp < kend ) 
 
163
 
 
164
                                if ( wp < kend )
165
165
                                        wp++;
166
 
                                else 
 
166
                                else
167
167
                                        break;
168
168
                                key_offset++;
169
169
                        }
170
 
                        
171
 
                        debug_printf("found wildcard '%c' at pos [%d]\n", 
 
170
 
 
171
                        debug_printf("found wildcard '%c' at pos [%d]\n",
172
172
                                next_wcard, (int) (wp-key));
173
 
        
174
 
                        if ( mvalues != NULL )                  
 
173
 
 
174
                        if ( mvalues != NULL )
175
175
                                str_truncate(mvalue, 0);
176
176
                } else {
177
177
                        /* Backtracked; '*' wildcard is retained */
178
178
                        debug_printf("backtracked");
179
179
                        backtrack = FALSE;
180
180
                }
181
 
                
 
181
 
182
182
                /* Determine what we are looking for */
183
183
                needle = str_c(section);
184
 
                nend = PTR_OFFSET(needle, str_len(section));            
185
 
                 
 
184
                nend = PTR_OFFSET(needle, str_len(section));
 
185
 
186
186
                debug_printf("  section needle:  '%s'\n", t_strdup_until(needle, nend));
187
187
                debug_printf("  section key:     '%s'\n", t_strdup_until(kp, kend));
188
188
                debug_printf("  section remnant: '%s'\n", t_strdup_until(wp, kend));
189
189
                debug_printf("  value remnant:   '%s'\n", t_strdup_until(vp, vend));
190
190
                debug_printf("  key offset:      %d\n", key_offset);
191
 
                
 
191
 
192
192
                pvp = vp;
193
193
                if ( next_wcard == '\0' ) {
194
194
                        /* No more wildcards; find the needle substring at the end of string */
195
 
        
 
195
 
196
196
                        const char *qp, *qend;
197
 
                        
198
 
                        debug_printf("next_wcard = NUL; must find needle at end\n");                             
199
 
 
200
 
                        /* Check if the value is still large enough */                  
 
197
 
 
198
                        debug_printf("next_wcard = NUL; must find needle at end\n");
 
199
 
 
200
                        /* Check if the value is still large enough */
201
201
                        if ( vend - str_len(section) < vp ) {
202
202
                                debug_printf("  wont match: value is too short\n");
203
203
                                break;
209
209
                        /* Record match values */
210
210
                        qend = vp;
211
211
                        qp = vp - key_offset;
212
 
                
 
212
 
213
213
                        if ( mvalues != NULL )
214
214
                                str_append_n(mvalue, pvp, qp-pvp);
215
 
                                        
 
215
 
216
216
                        /* Compare needle to end of value string */
217
 
                        if ( !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {   
218
 
                                debug_printf("  match at end failed\n");                                 
 
217
                        if ( !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {
 
218
                                debug_printf("  match at end failed\n");
219
219
                                break;
220
220
                        }
221
 
                        
 
221
 
222
222
                        /* Add match values */
223
223
                        if ( mvalues != NULL ) {
224
224
                                /* Append '*' match value */
226
226
 
227
227
                                /* Append any initial '?' match values */
228
228
                                for ( ; qp < qend; qp++ )
229
 
                                        sieve_match_values_add_char(mvalues, *qp); 
 
229
                                        sieve_match_values_add_char(mvalues, *qp);
230
230
                        }
231
231
 
232
232
                        /* Finish match */
244
244
                        const char *chars;
245
245
 
246
246
                        /* Reset '?' match values */
247
 
                        if ( mvalues != NULL )          
 
247
                        if ( mvalues != NULL )
248
248
                                str_truncate(mchars, 0);
249
 
                                                        
 
249
 
250
250
                        if ( wcard == '\0' ) {
251
251
                                /* No current wildcard; match needs to happen right at the beginning */
252
252
                                debug_printf("wcard = NUL; needle should be found at the beginning.\n");
253
253
                                debug_printf("  begin needle: '%s'\n", t_strdup_until(needle, nend));
254
254
                                debug_printf("  begin value:  '%s'\n", t_strdup_until(vp, vend));
255
255
 
256
 
                                if ( !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {   
257
 
                                        debug_printf("  failed to find needle at beginning\n");                          
 
256
                                if ( !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {
 
257
                                        debug_printf("  failed to find needle at beginning\n");
258
258
                                        break;
259
259
                                }
260
260
 
263
263
                                debug_printf("wcard != NUL; must find needle at an offset (>= %d).\n",
264
264
                                        key_offset);
265
265
 
266
 
                                /* Match may happen at any offset (>= key offset): find substring */                            
 
266
                                /* Match may happen at any offset (>= key offset): find substring */
267
267
                                vp += key_offset;
268
268
                                if ( (vp >= vend) || !_string_find(cmp, &vp, vend, &needle, nend) ) {
269
 
                                        debug_printf("  failed to find needle at an offset\n"); 
 
269
                                        debug_printf("  failed to find needle at an offset\n");
270
270
                                        break;
271
271
                                }
272
272
 
273
273
                                prv = vp - str_len(section);
274
274
                                prk = kp;
275
 
                                prw = wp;               
276
 
        
 
275
                                prw = wp;
 
276
 
277
277
                                /* Append match values */
278
278
                                if ( mvalues != NULL ) {
279
279
                                        const char *qend = vp - str_len(section);
289
289
                                                str_append_c(mchars, *qp);
290
290
                                }
291
291
                        }
292
 
                        
 
292
 
293
293
                        /* Update wildcard and key pointers for next wildcard scan */
294
294
                        if ( wp < kend ) wp++;
295
295
                        kp = wp;
296
 
                
 
296
 
297
297
                        /* Scan successive '?' wildcards */
298
298
                        while ( next_wcard == '?' ) {
299
299
                                debug_printf("next_wcard = '?'; need to match arbitrary character\n");
300
 
                                
301
 
                                /* Add match value */ 
 
300
 
 
301
                                /* Add match value */
302
302
                                if ( mvalues != NULL )
303
303
                                        str_append_c(mchars, *vp);
304
304
 
305
305
                                vp++;
306
306
 
307
 
                                /* Scan for next '?' wildcard */                                
 
307
                                /* Scan for next '?' wildcard */
308
308
                                next_wcard = _scan_key_section(subsection, &wp, kend);
309
 
                                debug_printf("found next wildcard '%c' at pos [%d] (fixed match)\n", 
 
309
                                debug_printf("found next wildcard '%c' at pos [%d] (fixed match)\n",
310
310
                                        next_wcard, (int) (wp-key));
311
 
                                        
 
311
 
312
312
                                /* Determine what we are looking for */
313
313
                                needle = str_c(subsection);
314
314
                                nend = PTR_OFFSET(needle, str_len(subsection));
317
317
                                debug_printf("  value remnant: '%s'\n", vp <= vend ? t_strdup_until(vp, vend) : "");
318
318
 
319
319
                                /* Try matching the needle at fixed position */
320
 
                                if ( (needle == nend && next_wcard == '\0' && vp < vend ) || 
321
 
                                        !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {        
322
 
                                        
 
320
                                if ( (needle == nend && next_wcard == '\0' && vp < vend ) ||
 
321
                                        !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {
 
322
 
323
323
                                        /* Match failed: now we have a problem. We need to backtrack to the previous
324
324
                                         * '*' wildcard occurence and start scanning for the next possible match.
325
325
                                         */
326
326
 
327
327
                                        debug_printf("  failed fixed match\n");
328
 
                                        
 
328
 
329
329
                                        /* Start backtrack */
330
330
                                        if ( prv != NULL && prv + 1 < vend ) {
331
331
                                                /* Restore pointers */
332
332
                                                vp = prv;
333
333
                                                kp = prk;
334
334
                                                wp = prw;
335
 
                                
 
335
 
336
336
                                                /* Skip forward one value character to scan the next possible match */
337
337
                                                if ( mvalues != NULL )
338
338
                                                        str_append_c(mvalue, *vp);
339
339
                                                vp++;
340
 
                                
 
340
 
341
341
                                                /* Set wildcard state appropriately */
342
342
                                                wcard = '*';
343
343
                                                next_wcard = '?';
344
 
                                
 
344
 
345
345
                                                /* Backtrack */
346
 
                                                backtrack = TRUE;                                
 
346
                                                backtrack = TRUE;
347
347
 
348
348
                                                debug_printf("  BACKTRACK\n");
349
349
                                        }
351
351
                                        /* Break '?' wildcard scanning loop */
352
352
                                        break;
353
353
                                }
354
 
                                
 
354
 
355
355
                                /* Update wildcard and key pointers for next wildcard scan */
356
356
                                if ( wp < kend ) wp++;
357
357
                                kp = wp;
358
358
                        }
359
 
                        
 
359
 
360
360
                        if ( !backtrack ) {
361
361
                                unsigned int i;
362
 
                                
 
362
 
363
363
                                if ( next_wcard == '?' ) {
364
 
                                        debug_printf("failed to match '?'\n");  
 
364
                                        debug_printf("failed to match '?'\n");
365
365
                                        break;
366
366
                                }
367
 
                                
 
367
 
368
368
                                if ( mvalues != NULL ) {
369
369
                                        if ( prv != NULL )
370
370
                                                sieve_match_values_add(mvalues, mvalue);
382
382
                                }
383
383
                        }
384
384
                }
385
 
                                        
386
 
                /* Check whether string ends in a wildcard 
 
385
 
 
386
                /* Check whether string ends in a wildcard
387
387
                 * (avoid scanning the rest of the string)
388
388
                 */
389
389
                if ( kp == kend && next_wcard == '*' ) {
393
393
                                str_append_n(mvalue, vp, vend-vp);
394
394
                                sieve_match_values_add(mvalues, mvalue);
395
395
                        }
396
 
                
 
396
 
397
397
                        /* Finish match */
398
398
                        kp = kend;
399
399
                        vp = vend;
400
 
                
 
400
 
401
401
                        debug_printf("key ends with '*'\n");
402
402
                        break;
403
 
                }                       
404
 
                                        
 
403
                }
 
404
 
405
405
                debug_printf("== Loop ==\n");
406
406
        }
407
407
 
413
413
        /* By definition, the match is only successful if both value and key pattern
414
414
         * are exhausted.
415
415
         */
416
 
        
 
416
 
417
417
        debug_printf("=== Finish ===\n");
418
418
        debug_printf("  result: %s\n", (kp == kend && vp == vend) ? "true" : "false");
419
 
        
 
419
 
420
420
        if (kp == kend && vp == vend) {
421
421
                /* Activate new match values after successful match */
422
422
                if ( mvalues != NULL ) {
434
434
        sieve_match_values_abort(&mvalues);
435
435
        return FALSE;
436
436
}
437
 
                         
 
437