Howdie all,
Attached there is a patch against mimedefang.c to enable multiline
responses. This was mentioned in the mailing list some time back and
was a todo on my private mimedefang list.
Can someone take a look at it, and implement it within mimedefang if you
like it. Now my c is kinda rusty so there might be some errors
somewhere, hey at least it compiles without errors :)
Guess I found Jan's extra second in 2005, better late than never.
Keep up the good work all,
--
Michiel
--- mimedefang.c.original 2009-06-09 00:20:53.000000000 +0200
+++ mimedefang.c 2009-06-09 21:57:06.000000000 +0200
@@ -216,6 +216,13 @@ static int set_reply(SMFICTX *ctx, char
/* Number of file descriptors to close when forking */
#define CLOSEFDS 256
+/* Amount of new lines in a response we want to handle (milters max is 32 do
not raise above that)
+ As it HAS to be NULL terminated the list is realy one smaller
+*/
+#define REPLY_MAX_BUFF_SIZE 32-1
+/* max string length of a reply to milter (max is 970 chars including \0 ) */
+#define REPLY_MAX_STR_LENGTH 970
+
/* Mutex to protect mkdir() calls */
static pthread_mutex_t MkdirMutex = PTHREAD_MUTEX_INITIALIZER;
@@ -336,6 +343,8 @@ set_reply(SMFICTX *ctx,
char const *reply)
{
char *safe_reply;
+ int retcode;
+
if (!reply || !*reply) {
if (*first == '4') {
reply = "Please try again later";
@@ -351,10 +360,8 @@ set_reply(SMFICTX *ctx,
if (*first == '4') dsn = "4.3.0";
else dsn = "5.7.1";
}
-
/* We need to double any "%" chars in reply */
if (strchr(reply, '%')) {
- int retcode;
char const *s;
char *t;
/* Worst-case, we'll double our length */
@@ -371,13 +378,73 @@ set_reply(SMFICTX *ctx,
*t++ = *s++;
}
*t = 0;
- retcode = smfi_setreply(ctx, (char *) code, (char *) dsn, safe_reply);
- free(safe_reply);
- return retcode;
}
-
+ else {
+ /* copy over the rely to safe_reply */
+ safe_reply = malloc(strlen(reply) + 1);
+ strncpy(safe_reply, reply, strlen(reply));
+ safe_reply[strlen(reply)]='\0';
+ }
+#ifdef MILTER_BUILDLIB_HAS_SETMLREPLY
+ // if we encounter a \n enter nasty milter phase
+ char *token = strtok(safe_reply, "\n");
+ if ( token != NULL ) {
+ int size = 0;
+ char *replyBuff[REPLY_MAX_BUFF_SIZE];
+ int i = -1;
+ while( token != NULL && ++i < REPLY_MAX_BUFF_SIZE ) {
+ // each reply cannot be large than MAX_REPLY_SIZE
+ size = (strlen(token) > REPLY_MAX_STR_LENGTH - 1 ?
REPLY_MAX_STR_LENGTH - 1 : strlen(token) );
+ if ( strlen(token) > size ) {
+ syslog(LOG_ERR, "Trunkating reply element [%d] too long", i);
+ }
+
+ if ( !(replyBuff[i] = malloc(size + 1)) ) {
+ syslog(LOG_ERR, "Out of memory splitting reply [%s]",token);
+ return smfi_setreply(ctx, (char *) code, (char *) dsn,
+ "Out of memory");
+ }
+ strncpy(replyBuff[i], token, size+1);
+ replyBuff[i][size+1]='\0';
+ token = strtok(NULL, "\n");
+ }
+ // notify someone if there are more enters in the safe_reply
+ // as we will not send them (specs u know).
+ if ( strtok(NULL, "\n") != NULL ) {
+ syslog(LOG_ERR, "Dropping extra reply elements");
+ }
+ // initialize all left over buffers
+ while( ++i < REPLY_MAX_BUFF_SIZE ) {
+ replyBuff[i] = NULL;
+ }
+ // send off the reply code (yes I know nasty, tell the milter ppl)
+ retcode = smfi_setmlreply(ctx, (char *) code, (char *) dsn,
+ replyBuff[0], replyBuff[1], replyBuff[2], replyBuff[3],
replyBuff[4],
+ replyBuff[5], replyBuff[6], replyBuff[7], replyBuff[8],
replyBuff[9],
+
replyBuff[10],replyBuff[11],replyBuff[12],replyBuff[13],replyBuff[14],
+
replyBuff[15],replyBuff[16],replyBuff[17],replyBuff[18],replyBuff[19],
+
replyBuff[20],replyBuff[21],replyBuff[22],replyBuff[23],replyBuff[24],
+
replyBuff[25],replyBuff[26],replyBuff[27],replyBuff[28],replyBuff[29],
+ replyBuff[30], NULL);
+ // prevent leaks and free
+ i = -1;
+ while( i++ > REPLY_MAX_BUFF_SIZE && replyBuff[i] != NULL ) {
+ free(replyBuff[i]);
+ }
+ free(safe_reply);
+ return retcode;
+ }
+#else
+ // no smfi_setmlreply support replace all \n with space
+ char *token = NULL;
+ while( (token = strchr(safe_reply, '\n')) != NULL) {
+ *token = ' ';
+ }
+#endif
/* smfi_setreply is not const-correct, hence the (char *) casts */
- return smfi_setreply(ctx, (char *) code, (char *) dsn, (char *) reply);
+ retcode = smfi_setreply(ctx, (char *) code, (char *) dsn, safe_reply);
+ free(safe_reply);
+ return retcode;
}
/**********************************************************************
_______________________________________________
NOTE: If there is a disclaimer or other legal boilerplate in the above
message, it is NULL AND VOID. You may ignore it.
Visit http://www.mimedefang.org and http://www.roaringpenguin.com
MIMEDefang mailing list MIMEDefang@lists.roaringpenguin.com
http://lists.roaringpenguin.com/mailman/listinfo/mimedefang