From a117714b88280a0ea42f531f9eb35befc11905c0 Mon Sep 17 00:00:00 2001 From: Tilghman Lesher Date: Thu, 18 Dec 2008 21:41:02 +0000 Subject: Merged revisions 165767 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r165767 | tilghman | 2008-12-18 15:14:47 -0600 (Thu, 18 Dec 2008) | 8 lines Add mutexes around accesses to the IMAP library interface. This prevents certain crashes, especially when shared mailboxes are used. (closes issue #13653) Reported by: howardwilkinson Patches: asterisk-1.4.21.2-appvoicemail-sharedimap-lock.patch uploaded by howardwilkinson (license 590) Tested by: jpeeler ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@165797 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_voicemail.c | 62 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index c993b1259..20dd25cd9 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -45,7 +45,7 @@ c-client (http://www.washington.edu/imap/ ***/ /*** MAKEOPTS - + odbc ltdl @@ -1462,7 +1462,9 @@ static void vm_imap_delete(int msgnum, struct ast_vm_user *vmu) ast_log(LOG_DEBUG, "deleting msgnum %d, which is mailbox message %lu\n",msgnum,messageNum); /* delete message */ snprintf (arg, sizeof(arg), "%lu",messageNum); + ast_mutex_lock(&vms->lock); mail_setflag (vms->mailstream,arg,"\\DELETED"); + ast_mutex_unlock(&vms->lock); } static int imap_retrieve_greeting (const char *dir, const int msgnum, struct ast_vm_user *vmu) @@ -1496,10 +1498,12 @@ static int imap_retrieve_greeting (const char *dir, const int msgnum, struct ast /* Greetings will never have a prepended message */ *vms_p->introfn = '\0'; - + + ast_mutex_lock(&vms_p->lock); ret = init_mailstream(vms_p, GREETINGS_FOLDER); if (!vms_p->mailstream) { ast_log(AST_LOG_ERROR, "IMAP mailstream is NULL\n"); + ast_mutex_unlock(&vms_p->lock); return -1; } @@ -1511,6 +1515,7 @@ static int imap_retrieve_greeting (const char *dir, const int msgnum, struct ast attachment = ast_strdupa(body->nested.part->next->body.parameter->value); } else { ast_log(AST_LOG_ERROR, "There is no file attached to this IMAP message.\n"); + ast_mutex_unlock(&vms_p->lock); return -1; } filename = strsep(&attachment, "."); @@ -1518,9 +1523,11 @@ static int imap_retrieve_greeting (const char *dir, const int msgnum, struct ast ast_copy_string(vms_p->fn, dir, sizeof(vms_p->fn)); vms_p->msgArray[vms_p->curmsg] = i + 1; save_body(body, vms_p, "2", attachment, 0); + ast_mutex_unlock(&vms_p->lock); return 0; } } + ast_mutex_unlock(&vms_p->lock); return -1; } @@ -1586,7 +1593,9 @@ static int imap_retrieve_file(const char *dir, const int msgnum, const char *mai } /* This will only work for new messages... */ + ast_mutex_lock(&vms->lock); header_content = mail_fetchheader (vms->mailstream, vms->msgArray[msgnum]); + ast_mutex_unlock(&vms->lock); /* empty string means no valid header */ if (ast_strlen_zero(header_content)) { ast_log (LOG_ERROR,"Could not fetch header for message number %ld\n",vms->msgArray[msgnum]); @@ -1594,8 +1603,10 @@ static int imap_retrieve_file(const char *dir, const int msgnum, const char *mai goto exit; } + ast_mutex_lock(&vms->lock); mail_fetchstructure (vms->mailstream,vms->msgArray[msgnum],&body); - + ast_mutex_unlock(&vms->lock); + /* We have the body, now we extract the file name of the first attachment. */ if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) { attachedfilefmt = ast_strdupa(body->nested.part->next->body.parameter->value); @@ -1764,6 +1775,7 @@ static int messagecount(const char *context, const char *mailbox, const char *fo return -1; } if (ret == 0) { + ast_mutex_lock(&vms_p->lock); pgm = mail_newsearchpgm (); hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", (char *)mailbox); pgm->header = hdr; @@ -1796,10 +1808,13 @@ static int messagecount(const char *context, const char *mailbox, const char *fo vms_p->urgentmessages = vms_p->vmArrayIndex; /*Freeing the searchpgm also frees the searchhdr*/ mail_free_searchpgm(&pgm); + ast_mutex_unlock(&vms_p->lock); vms_p->updated = 0; return vms_p->vmArrayIndex; - } else { + } else { + ast_mutex_lock(&vms_p->lock); mail_ping(vms_p->mailstream); + ast_mutex_unlock(&vms_p->lock); } return 0; } @@ -1897,8 +1912,10 @@ static int imap_store_file(char *dir, char *mailboxuser, char *mailboxcontext, i ret = init_mailstream(vms, NEW_FOLDER); if (ret == 0) { imap_mailbox_name(mailbox, sizeof(mailbox), vms, NEW_FOLDER, 1); + ast_mutex_lock(&vms->lock); if(!mail_append_full(vms->mailstream, mailbox, imap_flags, NIL, &str)) ast_log(LOG_ERROR, "Error while sending the message to %s\n", mailbox); + ast_mutex_unlock(&vms->lock); fclose(p); unlink(tmp); ast_free(buf); @@ -2062,8 +2079,12 @@ static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int i return -1; } snprintf(messagestring, sizeof(messagestring), "%ld", sendvms->msgArray[msgnum]); - if ((mail_copy(sendvms->mailstream, messagestring, (char *) mbox(imbox)) == T)) + ast_mutex_lock(&sendvms->lock); + if ((mail_copy(sendvms->mailstream, messagestring, (char *) mbox(imbox)) == T)) { + ast_mutex_unlock(&sendvms->lock); return 0; + } + ast_mutex_unlock(&sendvms->lock); ast_log(LOG_WARNING, "Unable to copy message from mailbox %s to mailbox %s\n", vmu->mailbox, recip->mailbox); return -1; } @@ -2199,6 +2220,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box) check_quota(vms,(char *)mbox(box)); } + ast_mutex_lock(&vms->lock); pgm = mail_newsearchpgm(); /* Check IMAP folder for Asterisk messages only... */ @@ -2230,6 +2252,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box) vms->lastmsg = vms->vmArrayIndex - 1; mail_free_searchpgm(&pgm); + ast_mutex_unlock(&vms->lock); return 0; } @@ -2238,9 +2261,9 @@ static void write_file(char *filename, char *buffer, unsigned long len) FILE *output; output = fopen (filename, "w"); - if (fwrite(buffer, len, 1, output) < len) { + if (fwrite(buffer, len, 1, output) != 1) { if (ferror(output)) { - ast_log(LOG_ERROR, "Short write while writing e-mail body.\n"); + ast_log(LOG_ERROR, "Short write while writing e-mail body: %s.\n", strerror(errno)); } } fclose (output); @@ -2720,7 +2743,9 @@ static int save_body(BODY *body, struct vm_state *vms, char *section, char *form if (!body || body == NIL) return -1; + ast_mutex_lock(&vms->lock); body_content = mail_fetchbody(vms->mailstream, vms->msgArray[vms->curmsg], section, &len); + ast_mutex_unlock(&vms->lock); if (body_content != NIL) { snprintf(filename, sizeof(filename), "%s.%s", fn, format); /* ast_debug(1,body_content); */ @@ -2743,6 +2768,7 @@ static int save_body(BODY *body, struct vm_state *vms, char *section, char *form * * Determines the delimiter character that is used by the underlying IMAP based mail store. */ +/* MUTEX should already be held */ static void get_mailbox_delimiter(MAILSTREAM *stream) { char tmp[50]; snprintf(tmp, sizeof(tmp), "{%s}", imapserver); @@ -2757,6 +2783,7 @@ static void get_mailbox_delimiter(MAILSTREAM *stream) { * Calls imap_getquotaroot, which will populate its results into the vm_state vms input structure. */ static void check_quota(struct vm_state *vms, char *mailbox) { + ast_mutex_lock(&vms->lock); mail_parameters(NULL, SET_QUOTA, (void *) mm_parsequota); ast_debug(3, "Mailbox name set to: %s, about to check quotas\n", mailbox); if (vms && vms->mailstream != NULL) { @@ -2764,6 +2791,7 @@ static void check_quota(struct vm_state *vms, char *mailbox) { } else { ast_log(AST_LOG_WARNING, "Mailstream not available for mailbox: %s\n", mailbox); } + ast_mutex_unlock(&vms->lock); } #endif /* IMAP_STORAGE */ @@ -5318,12 +5346,14 @@ leave_vm_out: /* expunge message - use UID Expunge if supported on IMAP server*/ ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n",expungeonhangup); if (expungeonhangup == 1) { + ast_mutex_lock(&vms->lock); #ifdef HAVE_IMAP_TK2006 if (LEVELUIDPLUS (vms->mailstream)) { mail_expunge_full(vms->mailstream,NIL,EX_UID); } else #endif mail_expunge(vms->mailstream); + ast_mutex_unlock(&vms->lock); } #endif @@ -5344,17 +5374,22 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg /* simple. huh? */ char sequence[10]; char mailbox[256]; + int res; + /* get the real IMAP message number for this message */ snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]); ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(box)); + ast_mutex_lock(&vms->lock); if (box == OLD_FOLDER) { mail_setflag(vms->mailstream, sequence, "\\Seen"); } else if (box == NEW_FOLDER) { mail_clearflag(vms->mailstream, sequence, "\\Seen"); } - if (!strcasecmp(mbox(NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) + if (!strcasecmp(mbox(NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) { + ast_mutex_unlock(&vms->lock); return 0; + } /* Create the folder if it don't exist */ imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */ ast_debug(5, "Checking if folder exists: %s\n",mailbox); @@ -5362,7 +5397,9 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg ast_debug(5, "Folder exists.\n"); else ast_log(AST_LOG_NOTICE, "Folder %s created!\n",mbox(box)); - return !mail_copy(vms->mailstream, sequence, (char *)mbox(box)); + res = !mail_copy(vms->mailstream, sequence, (char *)mbox(box)); + ast_mutex_unlock(&vms->lock); + return res; #else char *dir = vms->curdir; char *username = vms->username; @@ -6866,7 +6903,8 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms) ast_log(AST_LOG_ERROR, "Failed to procure file name from directory passed. You should never see this.\n"); return -1; } - + + ast_mutex_lock(&vms->lock); for (i = 0; i < vms->mailstream->nmsgs; i++) { mail_fetchstructure(vms->mailstream, i + 1, &body); /* We have the body, now we extract the file name of the first attachment. */ @@ -6874,6 +6912,7 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms) attachment = ast_strdupa(body->nested.part->next->body.parameter->value); } else { ast_log(AST_LOG_ERROR, "There is no file attached to this IMAP message.\n"); + ast_mutex_unlock(&vms->lock); return -1; } filename = strsep(&attachment, "."); @@ -6883,6 +6922,7 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms) } } mail_expunge(vms->mailstream); + ast_mutex_unlock(&vms->lock); return 0; } @@ -9439,12 +9479,14 @@ out: /* expunge message - use UID Expunge if supported on IMAP server*/ ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n",deleted,expungeonhangup); if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) { + ast_mutex_lock(&vms.lock); #ifdef HAVE_IMAP_TK2006 if (LEVELUIDPLUS (vms.mailstream)) { mail_expunge_full(vms.mailstream,NIL,EX_UID); } else #endif mail_expunge(vms.mailstream); + ast_mutex_unlock(&vms.lock); } /* before we delete the state, we should copy pertinent info * back to the persistent model */ -- cgit v1.2.3