]> code.citadel.org Git - citadel.git/commitdiff
* Fixed a potential buffer overflow in the message submit chain.
authorArt Cancro <ajc@citadel.org>
Wed, 4 Apr 2007 16:42:44 +0000 (16:42 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 4 Apr 2007 16:42:44 +0000 (16:42 +0000)
* Mailing list delivery now uses the message submit chain instead of
  generating queue instructions directly.  This greatly simplifies
  the code, and also allows non-SMTP recipients to be added to
  mailing lists.

citadel/msgbase.c
citadel/serv_network.c

index 5161bef7d45295a15703aa936c6b81721550d43a..3579dcb33067ecae481b0855589e4440109e3635 100644 (file)
@@ -150,6 +150,9 @@ int alias(char *name)
        char testnode[64];
        char buf[SIZ];
 
+       char original_name[256];
+       safestrncpy(original_name, name, sizeof original_name);
+
        striplt(name);
        remove_any_whitespace_to_the_left_or_right_of_at_symbol(name);
        stripallbut(name, '<', '>');
@@ -184,7 +187,9 @@ int alias(char *name)
                strcpy(name, aaa);
        }
 
-       lprintf(CTDL_INFO, "Mail is being forwarded to %s\n", name);
+       if (strcasecmp(original_name, name)) {
+               lprintf(CTDL_INFO, "%s is being forwarded to %s\n", original_name, name);
+       }
 
        /* Change "user @ xxx" to "user" if xxx is an alias for this host */
        for (a=0; a<strlen(name); ++a) {
@@ -2357,7 +2362,8 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
        FILE *network_fp = NULL;
        static int seqnum = 1;
        struct CtdlMessage *imsg = NULL;
-       char *instr;
+       char *instr = NULL;
+       size_t instr_alloc = 0;
        struct ser_ret smr;
        char *hold_R, *hold_D;
        char *collected_addresses = NULL;
@@ -2567,15 +2573,16 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,     /* message to save */
                if (getuser(&userbuf, recipient) == 0) {
                        // Add a flag so the Funambol module knows its mail
                        msg->cm_fields['W'] = strdup(recipient);
-                       MailboxName(actual_rm, sizeof actual_rm,
-                                       &userbuf, MAILROOM);
+                       MailboxName(actual_rm, sizeof actual_rm, &userbuf, MAILROOM);
                        CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0, msg);
                        BumpNewMailCounter(userbuf.usernum);
                        if (strlen(config.c_funambol_host) > 0) {
                        /* Generate a instruction message for the Funambol notification
-                          server, in the same style as the SMTP queue */
-                          instr = malloc(SIZ * 2);
-                          snprintf(instr, SIZ * 2,
+                        * server, in the same style as the SMTP queue
+                        */
+                          instr_alloc = 1024;
+                          instr = malloc(instr_alloc);
+                          snprintf(instr, instr_alloc,
                        "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
                        "bounceto|%s@%s\n",
                        SPOOLMIME, newmsgid, (long)time(NULL),
@@ -2589,7 +2596,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
                           imsg->cm_format_type = FMT_RFC822;
                           imsg->cm_fields['A'] = strdup("Citadel");
                           imsg->cm_fields['J'] = strdup("do not journal");
-                          imsg->cm_fields['M'] = instr;
+                          imsg->cm_fields['M'] = instr;        /* imsg owns this memory now */
                           imsg->cm_fields['W'] = strdup(recipient);
                           CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM);
                           CtdlFreeMessage(imsg);
@@ -2650,7 +2657,6 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
        /* Go back to the room we started from */
        lprintf(CTDL_DEBUG, "Returning to original room %s\n", hold_rm);
        if (strcasecmp(hold_rm, CC->room.QRname))
-               /* getroom(&CC->room, hold_rm); */
                usergoto(hold_rm, 0, 1, NULL, NULL);
 
        /* For internet mail, generate delivery instructions.
@@ -2661,8 +2667,9 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
        if (recps != NULL)
         if (recps->num_internet > 0) {
                lprintf(CTDL_DEBUG, "Generating delivery instructions\n");
-               instr = malloc(SIZ * 2);
-               snprintf(instr, SIZ * 2,
+               instr_alloc = 1024;
+               instr = malloc(instr_alloc);
+               snprintf(instr, instr_alloc,
                        "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
                        "bounceto|%s@%s\n",
                        SPOOLMIME, newmsgid, (long)time(NULL),
@@ -2671,10 +2678,12 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,     /* message to save */
 
                for (i=0; i<num_tokens(recps->recp_internet, '|'); ++i) {
                        size_t tmp = strlen(instr);
-                       extract_token(recipient, recps->recp_internet,
-                               i, '|', sizeof recipient);
-                       snprintf(&instr[tmp], SIZ * 2 - tmp,
-                                "remote|%s|0||\n", recipient);
+                       extract_token(recipient, recps->recp_internet, i, '|', sizeof recipient);
+                       if ((tmp + strlen(recipient) + 32) > instr_alloc) {
+                               instr_alloc = instr_alloc * 2;
+                               instr = realloc(instr, instr_alloc);
+                       }
+                       snprintf(&instr[tmp], instr_alloc - tmp, "remote|%s|0||\n", recipient);
                }
 
                imsg = malloc(sizeof(struct CtdlMessage));
@@ -2684,7 +2693,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
                imsg->cm_format_type = FMT_RFC822;
                imsg->cm_fields['A'] = strdup("Citadel");
                imsg->cm_fields['J'] = strdup("do not journal");
-               imsg->cm_fields['M'] = instr;
+               imsg->cm_fields['M'] = instr;   /* imsg owns this memory now */
                CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM);
                CtdlFreeMessage(imsg);
        }
index 930dae78528a727bde193d8cbacce1cc6c422bc0..1aaee9a32cbe2fc44559889871283d22535ee450 100644 (file)
@@ -427,10 +427,9 @@ void network_deliver_digest(struct SpoolControl *sc) {
        int i;
        struct CtdlMessage *msg = NULL;
        long msglen;
-       long msgnum;
-       char *instr = NULL;
-       size_t instr_len = SIZ;
-       struct CtdlMessage *imsg = NULL;
+       char *recps = NULL;
+       size_t recps_len = SIZ;
+       struct recptypes *valid;
        struct namelist *nptr;
 
        if (sc->num_msgs_spooled < 1) {
@@ -472,54 +471,38 @@ void network_deliver_digest(struct SpoolControl *sc) {
        fclose(sc->digestfp);
        sc->digestfp = NULL;
 
-       msgnum = CtdlSubmitMsg(msg, NULL, SMTP_SPOOLOUT_ROOM);
-       CtdlFreeMessage(msg);
-
        /* Now generate the delivery instructions */
 
        /* 
         * Figure out how big a buffer we need to allocate
         */
        for (nptr = sc->digestrecps; nptr != NULL; nptr = nptr->next) {
-               instr_len = instr_len + strlen(nptr->name) + 2;
+               recps_len = recps_len + strlen(nptr->name) + 2;
        }
        
-       /*
-        * allocate...
-        */
-       lprintf(CTDL_DEBUG, "Generating delivery instructions\n");
-       instr = malloc(instr_len);
-       if (instr == NULL) {
-               lprintf(CTDL_EMERG, "Cannot allocate %ld bytes for instr...\n",
-                       (long)instr_len);
+       recps = malloc(recps_len);
+
+       if (recps == NULL) {
+               lprintf(CTDL_EMERG, "Cannot allocate %ld bytes for recps...\n", (long)recps_len);
                abort();
        }
-       snprintf(instr, instr_len,
-               "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
-               "bounceto|postmaster@%s\n" ,
-               SPOOLMIME, msgnum, (long)time(NULL), config.c_fqdn );
 
-       /* Generate delivery instructions for each recipient */
+       strcpy(recps, "");
+
+       /* Each recipient */
        for (nptr = sc->digestrecps; nptr != NULL; nptr = nptr->next) {
-               size_t tmp = strlen(instr);
-               snprintf(&instr[tmp], instr_len - tmp,
-                        "remote|%s|0||\n", nptr->name);
+               if (nptr != sc->digestrecps) {
+                       strcat(recps, ",");
+               }
+               strcat(recps, nptr->name);
        }
 
-       /*
-        * Generate a message from the instructions
-        */
-       imsg = malloc(sizeof(struct CtdlMessage));
-       memset(imsg, 0, sizeof(struct CtdlMessage));
-       imsg->cm_magic = CTDLMESSAGE_MAGIC;
-       imsg->cm_anon_type = MES_NORMAL;
-       imsg->cm_format_type = FMT_RFC822;
-       imsg->cm_fields['A'] = strdup("Citadel");
-       imsg->cm_fields['M'] = instr;
-
-       /* Save delivery instructions in spoolout room */
-       CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM);
-       CtdlFreeMessage(imsg);
+       /* Now submit the message */
+       valid = validate_recipients(recps);
+       free(recps);
+       CtdlSubmitMsg(msg, valid, NULL);
+       CtdlFreeMessage(msg);
+       free_recipients(valid);
 }
 
 
@@ -527,62 +510,46 @@ void network_deliver_digest(struct SpoolControl *sc) {
  * Deliver list messages to everyone on the list ... efficiently
  */
 void network_deliver_list(struct CtdlMessage *msg, struct SpoolControl *sc) {
-       long msgnum;
-       char *instr = NULL;
-       size_t instr_len = SIZ;
-       struct CtdlMessage *imsg = NULL;
+       char *recps = NULL;
+       size_t recps_len = SIZ;
+       struct recptypes *valid;
        struct namelist *nptr;
 
        /* Don't do this if there were no recipients! */
        if (sc->listrecps == NULL) return;
 
-       /* Save the message to disk... */
-       msgnum = CtdlSubmitMsg(msg, NULL, SMTP_SPOOLOUT_ROOM);
-
        /* Now generate the delivery instructions */
 
        /* 
         * Figure out how big a buffer we need to allocate
         */
        for (nptr = sc->listrecps; nptr != NULL; nptr = nptr->next) {
-               instr_len = instr_len + strlen(nptr->name) + 2;
+               recps_len = recps_len + strlen(nptr->name) + 2;
        }
        
-       /*
-        * allocate...
-        */
-       lprintf(CTDL_DEBUG, "Generating delivery instructions\n");
-       instr = malloc(instr_len);
-       if (instr == NULL) {
-               lprintf(CTDL_EMERG, "Cannot allocate %ld bytes for instr...\n",
-                       (long)instr_len);
+       recps = malloc(recps_len);
+
+       if (recps == NULL) {
+               lprintf(CTDL_EMERG, "Cannot allocate %ld bytes for recps...\n", (long)recps_len);
                abort();
        }
-       snprintf(instr, instr_len,
-               "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
-               "bounceto|postmaster@%s\n" ,
-               SPOOLMIME, msgnum, (long)time(NULL), config.c_fqdn );
 
-       /* Generate delivery instructions for each recipient */
+       strcpy(recps, "");
+
+       /* Each recipient */
        for (nptr = sc->listrecps; nptr != NULL; nptr = nptr->next) {
-               size_t tmp = strlen(instr);
-               snprintf(&instr[tmp], instr_len - tmp, "remote|%s|0||\n", nptr->name);
+               if (nptr != sc->listrecps) {
+                       strcat(recps, ",");
+               }
+               strcat(recps, nptr->name);
        }
 
-       /*
-        * Generate a message from the instructions
-        */
-       imsg = malloc(sizeof(struct CtdlMessage));
-       memset(imsg, 0, sizeof(struct CtdlMessage));
-       imsg->cm_magic = CTDLMESSAGE_MAGIC;
-       imsg->cm_anon_type = MES_NORMAL;
-       imsg->cm_format_type = FMT_RFC822;
-       imsg->cm_fields['A'] = strdup("Citadel");
-       imsg->cm_fields['M'] = instr;
-
-       /* Save delivery instructions in spoolout room */
-       CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM);
-       CtdlFreeMessage(imsg);
+       /* Now submit the message */
+       valid = validate_recipients(recps);
+       free(recps);
+       CtdlSubmitMsg(msg, valid, NULL);
+       free_recipients(valid);
+       /* Do not call CtdlFreeMessage(msg) here; the caller will free it. */
 }