~ubuntu-branches/ubuntu/maverick/exim4/maverick-updates

« back to all changes in this revision

Viewing changes to src/dcc.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Bienia
  • Date: 2010-01-01 16:28:19 UTC
  • mfrom: (2.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20100101162819-htn71my7yj4v1vkr
Tags: 4.71-3ubuntu1
* Merge with Debian unstable (lp: #501657). Remaining changes:
  + debian/patches/71_exiq_grep_error_on_messages_without_size.dpatch:
    Improve handling of broken messages when "exim4 -bp" (mailq) reports
    lines without size info.
  + Don't declare a Provides: default-mta; in Ubuntu, we want postfix to be
    the default.
  + debian/control: Change build dependencies to MySQL 5.1.
  + debian/{control,rules}: add and enable hardened build for PIE
    (Debian bug 542726).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Cambridge: exim/exim-src/src/dcc.c,v 1.5 2009/11/12 08:34:23 nm4 Exp $ */
 
2
 
 
3
/*************************************************
 
4
*     Exim - an Internet mail transport agent    *
 
5
*************************************************/
 
6
 
 
7
/* Copyright (c) Wolfgang Breyha 2005-2009
 
8
 * Vienna University Computer Center
 
9
 * wbreyha@gmx.net
 
10
 * See the file NOTICE for conditions of use and distribution.
 
11
 */
 
12
 
 
13
/* This patch is based on code from Tom Kistners exiscan (ACL integration) and
 
14
 * the DCC local_scan patch from Christopher Bodenstein */
 
15
 
 
16
/* Code for calling dccifd. Called from acl.c. */
 
17
 
 
18
#include "exim.h"
 
19
#ifdef EXPERIMENTAL_DCC
 
20
#include "dcc.h"
 
21
#include "unistd.h"
 
22
 
 
23
uschar dcc_header_str[256];
 
24
uschar dcc_result_str[256];
 
25
int dcc_ok = 0;
 
26
int dcc_rc = 0;
 
27
 
 
28
/* This function takes a file descriptor and a buffer as input and
 
29
 * returns either 0 for success or errno in case of error. */
 
30
 
 
31
int flushbuffer (int socket, uschar *buffer)
 
32
 {
 
33
  int retval, rsp;
 
34
  rsp = write(socket, buffer, Ustrlen(buffer));
 
35
  DEBUG(D_acl)
 
36
    debug_printf("Result of the write() = %d\n", rsp);
 
37
  if(rsp < 0)
 
38
  {
 
39
    DEBUG(D_acl)
 
40
      debug_printf("Error writing buffer to socket: %s\n", strerror(errno));
 
41
    retval = errno;
 
42
  } else {
 
43
    DEBUG(D_acl)
 
44
      debug_printf("Wrote buffer to socket:\n%s\n", buffer);
 
45
    retval = 0;
 
46
  }
 
47
  return retval;
 
48
}
 
49
 
 
50
int dcc_process(uschar **listptr) {
 
51
  int sep = 0;
 
52
  uschar *list = *listptr;
 
53
  FILE *data_file;
 
54
  uschar *dcc_daemon_ip = US"";
 
55
  uschar *dcc_default_ip_option = US"127.0.0.1";
 
56
  uschar *dcc_ip_option = US"";
 
57
  uschar *dcc_helo_option = US"localhost";
 
58
  uschar *dcc_reject_message = US"Rejected by DCC";
 
59
  uschar *xtra_hdrs = NULL;
 
60
 
 
61
  /* from local_scan */
 
62
  int i, j, k, c, retval, sockfd, resp, line;
 
63
  unsigned int portnr;
 
64
  struct sockaddr_un  serv_addr;
 
65
  struct sockaddr_in  serv_addr_in;
 
66
  struct hostent *ipaddress;
 
67
  uschar sockpath[128];
 
68
  uschar sockip[40], client_ip[40];
 
69
  uschar opts[128];
 
70
  uschar rcpt[128], from[128];
 
71
  uschar sendbuf[4096];
 
72
  uschar recvbuf[4096];
 
73
  uschar xhdr[256];
 
74
  uschar dcc_return_text[1024];
 
75
  uschar mbox_path[1024];
 
76
  uschar message_subdir[2];
 
77
  struct header_line *dcchdr;
 
78
  uschar *dcc_acl_options;
 
79
  uschar dcc_acl_options_buffer[10];
 
80
  uschar dcc_xtra_hdrs[1024];
 
81
 
 
82
  /* grep 1st option */
 
83
  if ((dcc_acl_options = string_nextinlist(&list, &sep,
 
84
                                           dcc_acl_options_buffer,
 
85
                                           sizeof(dcc_acl_options_buffer))) != NULL)
 
86
  {
 
87
    /* parse 1st option */
 
88
    if ( (strcmpic(dcc_acl_options,US"false") == 0) ||
 
89
         (Ustrcmp(dcc_acl_options,"0") == 0) ) {
 
90
      /* explicitly no matching */
 
91
      return FAIL;
 
92
    };
 
93
 
 
94
    /* special cases (match anything except empty) */
 
95
    if ( (strcmpic(dcc_acl_options,US"true") == 0) ||
 
96
         (Ustrcmp(dcc_acl_options,"*") == 0) ||
 
97
         (Ustrcmp(dcc_acl_options,"1") == 0) ) {
 
98
      dcc_acl_options = dcc_acl_options;
 
99
    };
 
100
  }
 
101
  else {
 
102
    /* empty means "don't match anything" */
 
103
    return FAIL;
 
104
  };
 
105
 
 
106
  sep = 0;
 
107
 
 
108
  /* if we scanned this message last time, just return */
 
109
  if ( dcc_ok )
 
110
      return dcc_rc;
 
111
 
 
112
  /* open the spooled body */
 
113
  message_subdir[1] = '\0';
 
114
  for (i = 0; i < 2; i++) {
 
115
    message_subdir[0] = (split_spool_directory == (i == 0))? message_id[5] : 0;
 
116
    sprintf(CS mbox_path, "%s/input/%s/%s-D", spool_directory, message_subdir, message_id);
 
117
    data_file = Ufopen(mbox_path,"rb");
 
118
    if (data_file != NULL)
 
119
      break;
 
120
  };
 
121
 
 
122
  if (data_file == NULL) {
 
123
    /* error while spooling */
 
124
    log_write(0, LOG_MAIN|LOG_PANIC,
 
125
           "dcc acl condition: error while opening spool file");
 
126
    return DEFER;
 
127
  };
 
128
 
 
129
  /* Initialize the variables */
 
130
 
 
131
  bzero(sockip,sizeof(sockip));
 
132
  if (dccifd_address) {
 
133
    if (dccifd_address[0] == '/')
 
134
      Ustrncpy(sockpath, dccifd_address, sizeof(sockpath));
 
135
    else
 
136
      if( sscanf(CS dccifd_address, "%s %u", sockip, &portnr) != 2) {
 
137
        log_write(0, LOG_MAIN,
 
138
          "dcc acl condition: warning - invalid dccifd address: '%s'", dccifd_address);
 
139
        (void)fclose(data_file);
 
140
        return DEFER;
 
141
      }
 
142
  }
 
143
 
 
144
  /* opts is what we send as dccifd options - see man dccifd */
 
145
  /* We don't support any other option than 'header' so just copy that */
 
146
  bzero(opts,sizeof(opts));
 
147
  Ustrncpy(opts, "header", sizeof(opts)-1);
 
148
  Ustrncpy(client_ip, dcc_ip_option, sizeof(client_ip)-1);
 
149
  /* If the dcc_client_ip is not provided use the
 
150
   * sender_host_address or 127.0.0.1 if it is NULL */
 
151
  DEBUG(D_acl)
 
152
    debug_printf("my_ip_option = %s - client_ip = %s - sender_host_address = %s\n", dcc_ip_option, client_ip, sender_host_address);
 
153
  if(!(Ustrcmp(client_ip, ""))){
 
154
    /* Do we have a sender_host_address or is it NULL? */
 
155
    if(sender_host_address){
 
156
      Ustrncpy(client_ip, sender_host_address, sizeof(client_ip)-1);
 
157
    } else {
 
158
      /* sender_host_address is NULL which means it comes from localhost */
 
159
      Ustrncpy(client_ip, dcc_default_ip_option, sizeof(client_ip)-1);
 
160
    }
 
161
  }
 
162
  DEBUG(D_acl)
 
163
    debug_printf("Client IP: %s\n", client_ip);
 
164
  Ustrncpy(sockip, dcc_daemon_ip, sizeof(sockip)-1);
 
165
  /* strncat(opts, my_request, strlen(my_request)); */
 
166
  Ustrcat(opts, "\n");
 
167
  Ustrncat(opts, client_ip, sizeof(opts)-Ustrlen(opts)-1);
 
168
  Ustrncat(opts, "\nHELO ", sizeof(opts)-Ustrlen(opts)-1);
 
169
  Ustrncat(opts, dcc_helo_option, sizeof(opts)-Ustrlen(opts)-2);
 
170
  Ustrcat(opts, "\n");
 
171
 
 
172
  /* initialize the other variables */
 
173
  dcchdr = header_list;
 
174
  /* we set the default return value to DEFER */
 
175
  retval = DEFER;
 
176
 
 
177
  bzero(sendbuf,sizeof(sendbuf));
 
178
  bzero(xhdr,sizeof(xhdr));
 
179
  bzero(rcpt,sizeof(rcpt));
 
180
  bzero(from,sizeof(from));
 
181
 
 
182
  /* send a null return path as "<>". */
 
183
  if (Ustrlen(sender_address) > 0)
 
184
    Ustrncpy(from, sender_address, sizeof(from));
 
185
  else
 
186
    Ustrncpy(from, "<>", sizeof(from));
 
187
  Ustrncat(from, "\n", sizeof(from)-Ustrlen(from)-1);
 
188
 
 
189
  /**************************************
 
190
   * Now creating the socket connection *
 
191
   **************************************/
 
192
 
 
193
  /* If there is a dcc_daemon_ip, we use a tcp socket, otherwise a UNIX socket */
 
194
  if(Ustrcmp(sockip, "")){
 
195
    ipaddress = gethostbyname((char *)sockip);
 
196
    bzero((char *) &serv_addr_in, sizeof(serv_addr_in));
 
197
    serv_addr_in.sin_family = AF_INET;
 
198
    bcopy((char *)ipaddress->h_addr, (char *)&serv_addr_in.sin_addr.s_addr, ipaddress->h_length);
 
199
    serv_addr_in.sin_port = htons(portnr);
 
200
    if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) < 0){
 
201
      DEBUG(D_acl)
 
202
        debug_printf("Creating socket failed: %s\n", strerror(errno));
 
203
      log_write(0,LOG_REJECT,"Creating socket failed: %s\n", strerror(errno));
 
204
      /* if we cannot create the socket, defer the mail */
 
205
      (void)fclose(data_file);
 
206
      return retval;
 
207
    }
 
208
    /* Now connecting the socket (INET) */
 
209
    if (connect(sockfd, (struct sockaddr *)&serv_addr_in, sizeof(serv_addr_in)) < 0){
 
210
      DEBUG(D_acl)
 
211
        debug_printf("Connecting socket failed: %s\n", strerror(errno));
 
212
      log_write(0,LOG_REJECT,"Connecting socket failed: %s\n", strerror(errno));
 
213
      /* if we cannot contact the socket, defer the mail */
 
214
      (void)fclose(data_file);
 
215
      return retval;
 
216
    }
 
217
  } else {
 
218
    /* connecting to the dccifd UNIX socket */
 
219
    bzero((char *)&serv_addr,sizeof(serv_addr));
 
220
    serv_addr.sun_family = AF_UNIX;
 
221
    Ustrcpy(serv_addr.sun_path, sockpath);
 
222
    if ((sockfd = socket(AF_UNIX, SOCK_STREAM,0)) < 0){
 
223
      DEBUG(D_acl)
 
224
        debug_printf("Creating socket failed: %s\n", strerror(errno));
 
225
      log_write(0,LOG_REJECT,"Creating socket failed: %s\n", strerror(errno));
 
226
      /* if we cannot create the socket, defer the mail */
 
227
      (void)fclose(data_file);
 
228
      return retval;
 
229
    }
 
230
    /* Now connecting the socket (UNIX) */
 
231
    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
 
232
      DEBUG(D_acl)
 
233
                            debug_printf("Connecting socket failed: %s\n", strerror(errno));
 
234
      log_write(0,LOG_REJECT,"Connecting socket failed: %s\n", strerror(errno));
 
235
      /* if we cannot contact the socket, defer the mail */
 
236
      (void)fclose(data_file);
 
237
      return retval;
 
238
    }
 
239
  }
 
240
  /* the socket is open, now send the options to dccifd*/
 
241
  DEBUG(D_acl)
 
242
    debug_printf("\n---------------------------\nSocket opened; now sending input\n-----------------\n");
 
243
  /* First, fill in the input buffer */
 
244
  Ustrncpy(sendbuf, opts, sizeof(sendbuf));
 
245
  Ustrncat(sendbuf, from, sizeof(sendbuf)-Ustrlen(sendbuf)-1);
 
246
 
 
247
  DEBUG(D_acl)
 
248
  {
 
249
    debug_printf("opts = %s\nsender = %s\nrcpt count = %d\n", opts, from, recipients_count);
 
250
    debug_printf("Sending options:\n****************************\n");
 
251
  }
 
252
 
 
253
  /* let's send each of the recipients to dccifd */
 
254
  for (i = 0; i < recipients_count; i++){
 
255
    DEBUG(D_acl)
 
256
      debug_printf("recipient = %s\n",recipients_list[i].address);
 
257
    if(Ustrlen(sendbuf) + Ustrlen(recipients_list[i].address) > sizeof(sendbuf))
 
258
    {
 
259
      DEBUG(D_acl)
 
260
        debug_printf("Writing buffer: %s\n", sendbuf);
 
261
      flushbuffer(sockfd, sendbuf);
 
262
      bzero(sendbuf, sizeof(sendbuf));
 
263
    }
 
264
    Ustrncat(sendbuf, recipients_list[i].address, sizeof(sendbuf)-Ustrlen(sendbuf)-1);
 
265
    Ustrncat(sendbuf, "\r\n", sizeof(sendbuf)-Ustrlen(sendbuf)-1);
 
266
  }
 
267
  /* send a blank line between options and message */
 
268
  Ustrncat(sendbuf, "\n", sizeof(sendbuf)-Ustrlen(sendbuf)-1);
 
269
  /* Now we send the input buffer */
 
270
  DEBUG(D_acl)
 
271
    debug_printf("%s\n****************************\n", sendbuf);
 
272
  flushbuffer(sockfd, sendbuf);
 
273
 
 
274
  /* now send the message */
 
275
  /* Clear the input buffer */
 
276
  bzero(sendbuf, sizeof(sendbuf));
 
277
  /* First send the headers */
 
278
  /* Now send the headers */
 
279
  DEBUG(D_acl)
 
280
    debug_printf("Sending headers:\n****************************\n");
 
281
  Ustrncpy(sendbuf, dcchdr->text, sizeof(sendbuf)-2);
 
282
  while((dcchdr=dcchdr->next)) {
 
283
    if(dcchdr->slen > sizeof(sendbuf)-2) {
 
284
      /* The size of the header is bigger than the size of
 
285
       * the input buffer, so split it up in smaller parts. */
 
286
       flushbuffer(sockfd, sendbuf);
 
287
       bzero(sendbuf, sizeof(sendbuf));
 
288
       j = 0;
 
289
       while(j < dcchdr->slen)
 
290
       {
 
291
        for(i = 0; i < sizeof(sendbuf)-2; i++) {
 
292
          sendbuf[i] = dcchdr->text[j];
 
293
          j++;
 
294
        }
 
295
        flushbuffer(sockfd, sendbuf);
 
296
        bzero(sendbuf, sizeof(sendbuf));
 
297
       }
 
298
    } else if(Ustrlen(sendbuf) + dcchdr->slen > sizeof(sendbuf)-2) {
 
299
      flushbuffer(sockfd, sendbuf);
 
300
      bzero(sendbuf, sizeof(sendbuf));
 
301
      Ustrncpy(sendbuf, dcchdr->text, sizeof(sendbuf)-2);
 
302
    } else {
 
303
      Ustrncat(sendbuf, dcchdr->text, sizeof(sendbuf)-Ustrlen(sendbuf)-2);
 
304
    }
 
305
  }
 
306
 
 
307
  /* a blank line separates header from body */
 
308
  Ustrncat(sendbuf, "\n", sizeof(sendbuf)-Ustrlen(sendbuf)-1);
 
309
  flushbuffer(sockfd, sendbuf);
 
310
  DEBUG(D_acl)
 
311
    debug_printf("\n****************************\n%s", sendbuf);
 
312
 
 
313
  /* Clear the input buffer */
 
314
  bzero(sendbuf, sizeof(sendbuf));
 
315
 
 
316
  /* now send the body */
 
317
  DEBUG(D_acl)
 
318
    debug_printf("Writing body:\n****************************\n");
 
319
  (void)fseek(data_file, SPOOL_DATA_START_OFFSET, SEEK_SET);
 
320
  while((fread(sendbuf, 1, sizeof(sendbuf)-1, data_file)) > 0) {
 
321
    flushbuffer(sockfd, sendbuf);
 
322
    bzero(sendbuf, sizeof(sendbuf));
 
323
  }
 
324
  DEBUG(D_acl)
 
325
    debug_printf("\n****************************\n");
 
326
 
 
327
  /* shutdown() the socket */
 
328
  if(shutdown(sockfd, 1) < 0){
 
329
    DEBUG(D_acl)
 
330
      debug_printf("Couldn't shutdown socket: %s\n", strerror(errno));
 
331
    log_write(0,LOG_MAIN,"Couldn't shutdown socket: %s\n", strerror(errno));
 
332
    /* If there is a problem with the shutdown()
 
333
     * defer the mail. */
 
334
    (void)fclose(data_file);
 
335
    return retval;
 
336
  }
 
337
  DEBUG(D_acl)
 
338
    debug_printf("\n-------------------------\nInput sent.\n-------------------------\n");
 
339
 
 
340
    /********************************
 
341
   * receiving output from dccifd *
 
342
   ********************************/
 
343
  DEBUG(D_acl)
 
344
    debug_printf("\n-------------------------------------\nNow receiving output from server\n-----------------------------------\n");
 
345
 
 
346
  /******************************************************************
 
347
   * We should get 3 lines:                                         *
 
348
   * 1/ First line is overall result: either 'A' for Accept,        *
 
349
   *    'R' for Reject, 'S' for accept Some recipients or           *
 
350
   *    'T' for a Temporary error.                                  *
 
351
   * 2/ Second line contains the list of Accepted/Rejected          *
 
352
   *    recipients in the form AARRA (A = accepted, R = rejected).  *
 
353
   * 3/ Third line contains the X-DCC header.                       *
 
354
   ******************************************************************/
 
355
 
 
356
  line = 1;    /* we start at the first line of the output */
 
357
  j = 0;       /* will be used as index for the recipients list */
 
358
  k = 0;       /* initializing the index of the X-DCC header: xhdr[k] */
 
359
 
 
360
  /* Let's read from the socket until there's nothing left to read */
 
361
  bzero(recvbuf, sizeof(recvbuf));
 
362
  while((resp = read(sockfd, recvbuf, sizeof(recvbuf)-1)) > 0) {
 
363
    /* How much did we get from the socket */
 
364
    c = Ustrlen(recvbuf) + 1;
 
365
    DEBUG(D_acl)
 
366
      debug_printf("Length of the output buffer is: %d\nOutput buffer is:\n------------\n%s\n-----------\n", c, recvbuf);
 
367
 
 
368
    /* Now let's read each character and see what we've got */
 
369
    for(i = 0; i < c; i++) {
 
370
      /* First check if we reached the end of the line and
 
371
       * then increment the line counter */
 
372
      if(recvbuf[i] == '\n') {
 
373
        line++;
 
374
      }
 
375
      else {
 
376
        /* The first character of the first line is the
 
377
         * overall response. If there's another character
 
378
         * on that line it is not correct. */
 
379
        if(line == 1) {
 
380
          if(i == 0) {
 
381
            /* Now get the value and set the
 
382
             * return value accordingly */
 
383
            if(recvbuf[i] == 'A') {
 
384
              DEBUG(D_acl)
 
385
                debug_printf("Overall result = A\treturning OK\n");
 
386
              Ustrcpy(dcc_return_text, "Mail accepted by DCC");
 
387
              dcc_result = US"A";
 
388
              retval = OK;
 
389
            }
 
390
            else if(recvbuf[i] == 'R') {
 
391
              DEBUG(D_acl)
 
392
                debug_printf("Overall result = R\treturning FAIL\n");
 
393
              dcc_result = US"R";
 
394
              retval = FAIL;
 
395
              if(sender_host_name) {
 
396
                log_write(0, LOG_MAIN, "H=%s [%s] F=<%s>: rejected by DCC", sender_host_name, sender_host_address, sender_address);
 
397
              }
 
398
              else {
 
399
                log_write(0, LOG_MAIN, "H=[%s] F=<%s>: rejected by DCC", sender_host_address, sender_address);
 
400
              }
 
401
              Ustrncpy(dcc_return_text, dcc_reject_message, Ustrlen(dcc_reject_message) + 1);
 
402
            }
 
403
            else if(recvbuf[i] == 'S') {
 
404
              DEBUG(D_acl)
 
405
                debug_printf("Overall result  = S\treturning OK\n");
 
406
              Ustrcpy(dcc_return_text, "Not all recipients accepted by DCC");
 
407
              /* Since we're in an ACL we want a global result
 
408
               * so we accept for all */
 
409
              dcc_result = US"A";
 
410
              retval = OK;
 
411
            }
 
412
            else if(recvbuf[i] == 'G') {
 
413
              DEBUG(D_acl)
 
414
                debug_printf("Overall result  = G\treturning FAIL\n");
 
415
              Ustrcpy(dcc_return_text, "Greylisted by DCC");
 
416
              dcc_result = US"G";
 
417
              retval = FAIL;
 
418
            }
 
419
            else if(recvbuf[i] == 'T') {
 
420
              DEBUG(D_acl)
 
421
                debug_printf("Overall result = T\treturning DEFER\n");
 
422
              retval = DEFER;
 
423
              log_write(0,LOG_MAIN,"Temporary error with DCC: %s\n", recvbuf);
 
424
              Ustrcpy(dcc_return_text, "Temporary error with DCC");
 
425
              dcc_result = US"T";
 
426
            }
 
427
            else {
 
428
              DEBUG(D_acl)
 
429
                debug_printf("Overall result = something else\treturning DEFER\n");
 
430
              retval = DEFER;
 
431
              log_write(0,LOG_MAIN,"Unknown DCC response: %s\n", recvbuf);
 
432
              Ustrcpy(dcc_return_text, "Unknown DCC response");
 
433
              dcc_result = US"T";
 
434
            }
 
435
          }
 
436
          else {
 
437
          /* We're on the first line but not on the first character,
 
438
           * there must be something wrong. */
 
439
            DEBUG(D_acl)
 
440
              debug_printf("Line = %d but i = %d != 0  character is %c - This is wrong!\n", line, i, recvbuf[i]);
 
441
              log_write(0,LOG_MAIN,"Wrong header from DCC, output is %s\n", recvbuf);
 
442
          }
 
443
        }
 
444
        else if(line == 2) {
 
445
          /* On the second line we get a list of
 
446
           * answer for each recipient. We don't care about
 
447
           * it because we're in an acl and so just take the
 
448
           * global result. */
 
449
        }
 
450
        else if(line > 2) {
 
451
          /* The third and following lines is the X-DCC header,
 
452
           * so we store it in xhdr. */
 
453
          /* check if we don't get more than what we can handle */
 
454
          if(k < sizeof(xhdr)) { /* xhdr has a length of 120 */
 
455
            xhdr[k] = recvbuf[i];
 
456
            k++;
 
457
          }
 
458
          else {
 
459
            DEBUG(D_acl)
 
460
              debug_printf("We got more output than we can store in the X-DCC header. Truncating at 120 characters.\n");
 
461
          }
 
462
        }
 
463
        else {
 
464
          /* Wrong line number. There must be a problem with the output. */
 
465
          DEBUG(D_acl)
 
466
            debug_printf("Wrong line number in output. Line number is %d\n", line);
 
467
        }
 
468
      }
 
469
    }
 
470
    /* we reinitialize the output buffer before we read again */
 
471
    bzero(recvbuf,sizeof(recvbuf));
 
472
  }
 
473
  /* We have read everything from the socket */
 
474
 
 
475
  /* We need the terminate the X-DCC header with a '\n' character. This needs to be k-1
 
476
   * for xhdr[k] contains '\0'. */
 
477
  xhdr[k-1] = '\n';
 
478
 
 
479
  /* Now let's sum up what we've got. */
 
480
  DEBUG(D_acl)
 
481
    debug_printf("\n--------------------------\nOverall result = %d\nX-DCC header: %sReturn message: %s\ndcc_result: %s\n", retval, xhdr, dcc_return_text, dcc_result);
 
482
 
 
483
  /* We only add the X-DCC header if it starts with X-DCC */
 
484
  if(!(Ustrncmp(xhdr, "X-DCC", 5))){
 
485
    dcc_header = xhdr;
 
486
    if(dcc_direct_add_header) {
 
487
      header_add(' ' , "%s", xhdr);
 
488
  /* since the MIME ACL already writes the .eml file to disk without DCC Header we've to erase it */
 
489
      unspool_mbox();
 
490
    }
 
491
  }
 
492
  else {
 
493
    DEBUG(D_acl)
 
494
      debug_printf("Wrong format of the X-DCC header: %s\n", xhdr);
 
495
  }
 
496
 
 
497
  /* check if we should add additional headers passed in acl_m_dcc_add_header */
 
498
  if(dcc_direct_add_header) {
 
499
    if (((xtra_hdrs = expand_string(US"$acl_m_dcc_add_header")) != NULL) && (xtra_hdrs[0] != '\0')) {
 
500
      Ustrncpy(dcc_xtra_hdrs, xtra_hdrs, sizeof(dcc_xtra_hdrs) - 2);
 
501
      if (dcc_xtra_hdrs[Ustrlen(dcc_xtra_hdrs)-1] != '\n')
 
502
        Ustrcat(dcc_xtra_hdrs, "\n");
 
503
      header_add(' ', "%s", dcc_xtra_hdrs);
 
504
      DEBUG(D_acl)
 
505
        debug_printf("adding additional headers in $acl_m_dcc_add_header: %s", dcc_xtra_hdrs);
 
506
    }
 
507
  }
 
508
 
 
509
  dcc_ok = 1;
 
510
  /* Now return to exim main process */
 
511
  DEBUG(D_acl)
 
512
    debug_printf("Before returning to exim main process:\nreturn_text = %s - retval = %d\ndcc_result = %s\n", dcc_return_text, retval, dcc_result);
 
513
 
 
514
  (void)fclose(data_file);
 
515
  return retval;
 
516
}
 
517
 
 
518
#endif