~ubuntu-branches/ubuntu/hardy/exim4/hardy-proposed

« back to all changes in this revision

Viewing changes to src/bmi_spam.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Haber
  • Date: 2005-07-02 06:08:34 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050702060834-qk17pd52kb9nt3bj
Tags: 4.52-1
* new upstream version 4.51. (mh)
  * adapt 70_remove_exim-users_references
  * remove 37_gnutlsparams
  * adapt 36_pcre
  * adapt 31_eximmanpage
* fix package priorities to have them in sync with override again. (mh)
* Fix error in nb (Norwegian) translation.
  Thanks to Helge Hafting. (mh). Closes: #315775
* Standards-Version: 3.6.2, no changes needed. (mh)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Cambridge: exim/exim-src/src/bmi_spam.c,v 1.4 2005/06/22 15:44:37 ph10 Exp $ */
 
2
 
 
3
/*************************************************
 
4
*     Exim - an Internet mail transport agent    *
 
5
*************************************************/
 
6
 
 
7
/* Code for calling Brightmail AntiSpam.
 
8
   Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
 
9
   License: GPL */
 
10
 
 
11
#include "exim.h"
 
12
#ifdef EXPERIMENTAL_BRIGHTMAIL
 
13
 
 
14
#include "bmi_spam.h"
 
15
 
 
16
uschar *bmi_current_optin = NULL;
 
17
 
 
18
uschar *bmi_process_message(header_line *header_list, int data_fd) {
 
19
  BmiSystem *system = NULL;
 
20
  BmiMessage *message = NULL;
 
21
  BmiError err;
 
22
  BmiErrorLocation err_loc;
 
23
  BmiErrorType err_type;
 
24
  const BmiVerdict *verdict = NULL;
 
25
  FILE *data_file;
 
26
  uschar data_buffer[4096];
 
27
  uschar localhost[] = "127.0.0.1";
 
28
  uschar *host_address;
 
29
  uschar *verdicts = NULL;
 
30
  int i,j;
 
31
 
 
32
  err = bmiInitSystem(BMI_VERSION, (char *)bmi_config_file, &system);
 
33
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
34
    err_loc = bmiErrorGetLocation(err);
 
35
    err_type = bmiErrorGetType(err);
 
36
    log_write(0, LOG_PANIC,
 
37
               "bmi error [loc %d type %d]: could not initialize Brightmail system.", (int)err_loc, (int)err_type);
 
38
    return NULL;
 
39
  }
 
40
 
 
41
  err = bmiInitMessage(system, &message);
 
42
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
43
    err_loc = bmiErrorGetLocation(err);
 
44
    err_type = bmiErrorGetType(err);
 
45
    log_write(0, LOG_PANIC,
 
46
               "bmi error [loc %d type %d]: could not initialize Brightmail message.", (int)err_loc, (int)err_type);
 
47
    bmiFreeSystem(system);
 
48
    return NULL;
 
49
  }
 
50
 
 
51
  /* Send IP address of sending host */
 
52
  if (sender_host_address == NULL)
 
53
    host_address = localhost;
 
54
  else
 
55
    host_address = sender_host_address;
 
56
  err = bmiProcessConnection((char *)host_address, message);
 
57
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
58
    err_loc = bmiErrorGetLocation(err);
 
59
    err_type = bmiErrorGetType(err);
 
60
    log_write(0, LOG_PANIC,
 
61
               "bmi error [loc %d type %d]: bmiProcessConnection() failed (IP %s).", (int)err_loc, (int)err_type, (char *)host_address);
 
62
    bmiFreeMessage(message);
 
63
    bmiFreeSystem(system);
 
64
    return NULL;
 
65
  };
 
66
 
 
67
  /* Send envelope sender address */
 
68
  err = bmiProcessFROM((char *)sender_address, message);
 
69
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
70
    err_loc = bmiErrorGetLocation(err);
 
71
    err_type = bmiErrorGetType(err);
 
72
    log_write(0, LOG_PANIC,
 
73
               "bmi error [loc %d type %d]: bmiProcessFROM() failed (address %s).", (int)err_loc, (int)err_type, (char *)sender_address);
 
74
    bmiFreeMessage(message);
 
75
    bmiFreeSystem(system);
 
76
    return NULL;
 
77
  };
 
78
 
 
79
  /* Send envelope recipients */
 
80
  for(i=0;i<recipients_count;i++) {
 
81
    recipient_item *r = recipients_list + i;
 
82
    BmiOptin *optin = NULL;
 
83
 
 
84
    /* create optin object if optin string is given */
 
85
    if ((r->bmi_optin != NULL) && (Ustrlen(r->bmi_optin) > 1)) {
 
86
      debug_printf("passing bmiOptin string: %s\n", r->bmi_optin);
 
87
      bmiOptinInit(&optin);
 
88
      err = bmiOptinMset(optin, r->bmi_optin, ':');
 
89
      if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
90
        log_write(0, LOG_PANIC|LOG_MAIN,
 
91
                   "bmi warning: [loc %d type %d]: bmiOptinMSet() failed (address '%s', string '%s').", (int)err_loc, (int)err_type, (char *)r->address, (char *)r->bmi_optin);
 
92
        if (optin != NULL)
 
93
          bmiOptinFree(optin);
 
94
        optin = NULL;
 
95
      };
 
96
    };
 
97
 
 
98
    err = bmiAccumulateTO((char *)r->address, optin, message);
 
99
 
 
100
    if (optin != NULL)
 
101
      bmiOptinFree(optin);
 
102
 
 
103
    if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
104
      err_loc = bmiErrorGetLocation(err);
 
105
      err_type = bmiErrorGetType(err);
 
106
      log_write(0, LOG_PANIC,
 
107
                 "bmi error [loc %d type %d]: bmiAccumulateTO() failed (address %s).", (int)err_loc, (int)err_type, (char *)r->address);
 
108
      bmiFreeMessage(message);
 
109
      bmiFreeSystem(system);
 
110
      return NULL;
 
111
    };
 
112
  };
 
113
  err = bmiEndTO(message);
 
114
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
115
    err_loc = bmiErrorGetLocation(err);
 
116
    err_type = bmiErrorGetType(err);
 
117
    log_write(0, LOG_PANIC,
 
118
               "bmi error [loc %d type %d]: bmiEndTO() failed.", (int)err_loc, (int)err_type);
 
119
    bmiFreeMessage(message);
 
120
    bmiFreeSystem(system);
 
121
    return NULL;
 
122
  };
 
123
 
 
124
  /* Send message headers */
 
125
  while (header_list != NULL) {
 
126
    /* skip deleted headers */
 
127
    if (header_list->type == '*') {
 
128
      header_list = header_list->next;
 
129
      continue;
 
130
    };
 
131
    err = bmiAccumulateHeaders((const char *)header_list->text, header_list->slen, message);
 
132
    if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
133
      err_loc = bmiErrorGetLocation(err);
 
134
      err_type = bmiErrorGetType(err);
 
135
      log_write(0, LOG_PANIC,
 
136
                 "bmi error [loc %d type %d]: bmiAccumulateHeaders() failed.", (int)err_loc, (int)err_type);
 
137
      bmiFreeMessage(message);
 
138
      bmiFreeSystem(system);
 
139
      return NULL;
 
140
    };
 
141
    header_list = header_list->next;
 
142
  };
 
143
  err = bmiEndHeaders(message);
 
144
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
145
    err_loc = bmiErrorGetLocation(err);
 
146
    err_type = bmiErrorGetType(err);
 
147
    log_write(0, LOG_PANIC,
 
148
               "bmi error [loc %d type %d]: bmiEndHeaders() failed.", (int)err_loc, (int)err_type);
 
149
    bmiFreeMessage(message);
 
150
    bmiFreeSystem(system);
 
151
    return NULL;
 
152
  };
 
153
 
 
154
  /* Send body */
 
155
  data_file = fdopen(data_fd,"r");
 
156
  do {
 
157
    j = fread(data_buffer, 1, sizeof(data_buffer), data_file);
 
158
    if (j > 0) {
 
159
      err = bmiAccumulateBody((const char *)data_buffer, j, message);
 
160
      if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
161
        err_loc = bmiErrorGetLocation(err);
 
162
        err_type = bmiErrorGetType(err);
 
163
        log_write(0, LOG_PANIC,
 
164
                   "bmi error [loc %d type %d]: bmiAccumulateBody() failed.", (int)err_loc, (int)err_type);
 
165
        bmiFreeMessage(message);
 
166
        bmiFreeSystem(system);
 
167
        return NULL;
 
168
      };
 
169
    };
 
170
  } while (j > 0);
 
171
  err = bmiEndBody(message);
 
172
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
173
    err_loc = bmiErrorGetLocation(err);
 
174
    err_type = bmiErrorGetType(err);
 
175
    log_write(0, LOG_PANIC,
 
176
               "bmi error [loc %d type %d]: bmiEndBody() failed.", (int)err_loc, (int)err_type);
 
177
    bmiFreeMessage(message);
 
178
    bmiFreeSystem(system);
 
179
    return NULL;
 
180
  };
 
181
 
 
182
 
 
183
  /* End message */
 
184
  err = bmiEndMessage(message);
 
185
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
186
    err_loc = bmiErrorGetLocation(err);
 
187
    err_type = bmiErrorGetType(err);
 
188
    log_write(0, LOG_PANIC,
 
189
               "bmi error [loc %d type %d]: bmiEndMessage() failed.", (int)err_loc, (int)err_type);
 
190
    bmiFreeMessage(message);
 
191
    bmiFreeSystem(system);
 
192
    return NULL;
 
193
  };
 
194
 
 
195
  /* get store for the verdict string */
 
196
  verdicts = store_get(1);
 
197
  *verdicts = '\0';
 
198
 
 
199
  for ( err = bmiAccessFirstVerdict(message, &verdict);
 
200
        verdict != NULL;
 
201
        err = bmiAccessNextVerdict(message, verdict, &verdict) ) {
 
202
    char *verdict_str;
 
203
 
 
204
    err = bmiCreateStrFromVerdict(verdict,&verdict_str);
 
205
    if (!store_extend(verdicts, Ustrlen(verdicts)+1, Ustrlen(verdicts)+1+strlen(verdict_str)+1)) {
 
206
      /* can't allocate more store */
 
207
      return NULL;
 
208
    };
 
209
    if (*verdicts != '\0')
 
210
      Ustrcat(verdicts, US ":");
 
211
    Ustrcat(verdicts, US verdict_str);
 
212
    bmiFreeStr(verdict_str);
 
213
  };
 
214
 
 
215
  DEBUG(D_receive) debug_printf("bmi verdicts: %s\n", verdicts);
 
216
 
 
217
  if (Ustrlen(verdicts) == 0)
 
218
    return NULL;
 
219
  else
 
220
    return verdicts;
 
221
}
 
222
 
 
223
 
 
224
int bmi_get_delivery_status(uschar *base64_verdict) {
 
225
  BmiError err;
 
226
  BmiErrorLocation err_loc;
 
227
  BmiErrorType err_type;
 
228
  BmiVerdict *verdict = NULL;
 
229
  int rc = 1;   /* deliver by default */
 
230
 
 
231
  /* always deliver when there is no verdict */
 
232
  if (base64_verdict == NULL)
 
233
    return 1;
 
234
 
 
235
  /* create verdict from base64 string */
 
236
  err = bmiCreateVerdictFromStr(CS base64_verdict, &verdict);
 
237
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
238
    err_loc = bmiErrorGetLocation(err);
 
239
    err_type = bmiErrorGetType(err);
 
240
    log_write(0, LOG_PANIC,
 
241
               "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
 
242
    return 1;
 
243
  };
 
244
 
 
245
  err = bmiVerdictError(verdict);
 
246
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
247
    /* deliver normally due to error */
 
248
    rc = 1;
 
249
  }
 
250
  else if (bmiVerdictDestinationIsDefault(verdict) == BMI_TRUE) {
 
251
    /* deliver normally */
 
252
    rc = 1;
 
253
  }
 
254
  else if (bmiVerdictAccessDestination(verdict) == NULL) {
 
255
    /* do not deliver */
 
256
    rc = 0;
 
257
  }
 
258
  else {
 
259
    /* deliver to alternate location */
 
260
    rc = 1;
 
261
  };
 
262
 
 
263
  bmiFreeVerdict(verdict);
 
264
  return rc;
 
265
}
 
266
 
 
267
 
 
268
uschar *bmi_get_alt_location(uschar *base64_verdict) {
 
269
  BmiError err;
 
270
  BmiErrorLocation err_loc;
 
271
  BmiErrorType err_type;
 
272
  BmiVerdict *verdict = NULL;
 
273
  uschar *rc = NULL;
 
274
 
 
275
  /* always deliver when there is no verdict */
 
276
  if (base64_verdict == NULL)
 
277
    return NULL;
 
278
 
 
279
  /* create verdict from base64 string */
 
280
  err = bmiCreateVerdictFromStr(CS base64_verdict, &verdict);
 
281
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
282
    err_loc = bmiErrorGetLocation(err);
 
283
    err_type = bmiErrorGetType(err);
 
284
    log_write(0, LOG_PANIC,
 
285
               "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
 
286
    return NULL;
 
287
  };
 
288
 
 
289
  err = bmiVerdictError(verdict);
 
290
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
291
    /* deliver normally due to error */
 
292
    rc = NULL;
 
293
  }
 
294
  else if (bmiVerdictDestinationIsDefault(verdict) == BMI_TRUE) {
 
295
    /* deliver normally */
 
296
    rc = NULL;
 
297
  }
 
298
  else if (bmiVerdictAccessDestination(verdict) == NULL) {
 
299
    /* do not deliver */
 
300
    rc = NULL;
 
301
  }
 
302
  else {
 
303
    /* deliver to alternate location */
 
304
    rc = store_get(strlen(bmiVerdictAccessDestination(verdict))+1);
 
305
    Ustrcpy(rc, bmiVerdictAccessDestination(verdict));
 
306
    rc[strlen(bmiVerdictAccessDestination(verdict))] = '\0';
 
307
  };
 
308
 
 
309
  bmiFreeVerdict(verdict);
 
310
  return rc;
 
311
}
 
312
 
 
313
uschar *bmi_get_base64_verdict(uschar *bmi_local_part, uschar *bmi_domain) {
 
314
  BmiError err;
 
315
  BmiErrorLocation err_loc;
 
316
  BmiErrorType err_type;
 
317
  BmiVerdict *verdict = NULL;
 
318
  const BmiRecipient *recipient = NULL;
 
319
  const char *verdict_str = NULL;
 
320
  uschar *verdict_ptr;
 
321
  uschar *verdict_buffer = NULL;
 
322
  int sep = 0;
 
323
 
 
324
  /* return nothing if there are no verdicts available */
 
325
  if (bmi_verdicts == NULL)
 
326
    return NULL;
 
327
 
 
328
  /* allocate room for the b64 verdict string */
 
329
  verdict_buffer = store_get(Ustrlen(bmi_verdicts)+1);
 
330
 
 
331
  /* loop through verdicts */
 
332
  verdict_ptr = bmi_verdicts;
 
333
  while ((verdict_str = (const char *)string_nextinlist(&verdict_ptr, &sep,
 
334
                                          verdict_buffer,
 
335
                                          Ustrlen(bmi_verdicts)+1)) != NULL) {
 
336
 
 
337
    /* create verdict from base64 string */
 
338
    err = bmiCreateVerdictFromStr(verdict_str, &verdict);
 
339
    if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
340
      err_loc = bmiErrorGetLocation(err);
 
341
      err_type = bmiErrorGetType(err);
 
342
      log_write(0, LOG_PANIC,
 
343
                 "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, verdict_str);
 
344
      return NULL;
 
345
    };
 
346
 
 
347
    /* loop through rcpts for this verdict */
 
348
    for ( recipient = bmiVerdictAccessFirstRecipient(verdict);
 
349
          recipient != NULL;
 
350
          recipient = bmiVerdictAccessNextRecipient(verdict, recipient)) {
 
351
      uschar *rcpt_local_part;
 
352
      uschar *rcpt_domain;
 
353
 
 
354
      /* compare address against our subject */
 
355
      rcpt_local_part = (unsigned char *)bmiRecipientAccessAddress(recipient);
 
356
      rcpt_domain = Ustrchr(rcpt_local_part,'@');
 
357
      if (rcpt_domain == NULL) {
 
358
        rcpt_domain = US"";
 
359
      }
 
360
      else {
 
361
        *rcpt_domain = '\0';
 
362
        rcpt_domain++;
 
363
      };
 
364
 
 
365
      if ( (strcmpic(rcpt_local_part, bmi_local_part) == 0) &&
 
366
           (strcmpic(rcpt_domain, bmi_domain) == 0) ) {
 
367
        /* found verdict */
 
368
        bmiFreeVerdict(verdict);
 
369
        return (uschar *)verdict_str;
 
370
      };
 
371
    };
 
372
 
 
373
    bmiFreeVerdict(verdict);
 
374
  };
 
375
 
 
376
  return NULL;
 
377
}
 
378
 
 
379
 
 
380
uschar *bmi_get_base64_tracker_verdict(uschar *base64_verdict) {
 
381
  BmiError err;
 
382
  BmiErrorLocation err_loc;
 
383
  BmiErrorType err_type;
 
384
  BmiVerdict *verdict = NULL;
 
385
  uschar *rc = NULL;
 
386
 
 
387
  /* always deliver when there is no verdict */
 
388
  if (base64_verdict == NULL)
 
389
    return NULL;
 
390
 
 
391
  /* create verdict from base64 string */
 
392
  err = bmiCreateVerdictFromStr(CS base64_verdict, &verdict);
 
393
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
394
    err_loc = bmiErrorGetLocation(err);
 
395
    err_type = bmiErrorGetType(err);
 
396
    log_write(0, LOG_PANIC,
 
397
               "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
 
398
    return NULL;
 
399
  };
 
400
 
 
401
  /* create old tracker string from verdict */
 
402
  err = bmiCreateOldStrFromVerdict(verdict, &rc);
 
403
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
404
    err_loc = bmiErrorGetLocation(err);
 
405
    err_type = bmiErrorGetType(err);
 
406
    log_write(0, LOG_PANIC,
 
407
               "bmi error [loc %d type %d]: bmiCreateOldStrFromVerdict() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
 
408
    return NULL;
 
409
  };
 
410
 
 
411
  bmiFreeVerdict(verdict);
 
412
  return rc;
 
413
}
 
414
 
 
415
 
 
416
int bmi_check_rule(uschar *base64_verdict, uschar *option_list) {
 
417
  BmiError err;
 
418
  BmiErrorLocation err_loc;
 
419
  BmiErrorType err_type;
 
420
  BmiVerdict *verdict = NULL;
 
421
  int rc = 0;
 
422
  uschar *rule_num;
 
423
  uschar *rule_ptr;
 
424
  uschar rule_buffer[32];
 
425
  int sep = 0;
 
426
 
 
427
 
 
428
  /* no verdict -> no rule fired */
 
429
  if (base64_verdict == NULL)
 
430
    return 0;
 
431
 
 
432
  /* create verdict from base64 string */
 
433
  err = bmiCreateVerdictFromStr(CS base64_verdict, &verdict);
 
434
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
435
    err_loc = bmiErrorGetLocation(err);
 
436
    err_type = bmiErrorGetType(err);
 
437
    log_write(0, LOG_PANIC,
 
438
               "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
 
439
    return 0;
 
440
  };
 
441
 
 
442
  err = bmiVerdictError(verdict);
 
443
  if (bmiErrorIsFatal(err) == BMI_TRUE) {
 
444
    /* error -> no rule fired */
 
445
    bmiFreeVerdict(verdict);
 
446
    return 0;
 
447
  }
 
448
 
 
449
  /* loop through numbers */
 
450
  rule_ptr = option_list;
 
451
  while ((rule_num = string_nextinlist(&rule_ptr, &sep,
 
452
                                       rule_buffer, 32)) != NULL) {
 
453
    int rule_int = -1;
 
454
 
 
455
    /* try to translate to int */
 
456
    (void)sscanf(rule_num, "%d", &rule_int);
 
457
    if (rule_int > 0) {
 
458
      debug_printf("checking rule #%d\n", rule_int);
 
459
      /* check if rule fired on the message */
 
460
      if (bmiVerdictRuleFired(verdict, rule_int) == BMI_TRUE) {
 
461
        debug_printf("rule #%d fired\n", rule_int);
 
462
        rc = 1;
 
463
        break;
 
464
      };
 
465
    };
 
466
  };
 
467
 
 
468
  bmiFreeVerdict(verdict);
 
469
  return rc;
 
470
};
 
471
 
 
472
#endif