Index: apps/app_voicemail.c =================================================================== --- apps/app_voicemail.c (revision 169203) +++ apps/app_voicemail.c (working copy) @@ -406,6 +406,7 @@ #define VM_MOVEHEARD (1 << 16) /*!< Move a "heard" message to Old after listening to it */ #define VM_MESSAGEWRAP (1 << 17) /*!< Wrap around from the last message to the first, and vice-versa */ #define VM_FWDURGAUTO (1 << 18) /*!< Autoset of Urgent flag on forwarded Urgent messages set globally */ +#define VM_SECRETINSPOOL (1 << 16) /*!< vmsecret is read/write to users voicemail spool directory instead of config file */ #define ERROR_LOCK_PATH -100 @@ -804,6 +805,7 @@ static void apply_options(struct ast_vm_user *vmu, const char *options); static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum); static int is_valid_dtmf(const char *key); +static void read_secret_from_file(char *secretfn, char *password, int passwordlen); #if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE)) static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit); @@ -1261,9 +1263,31 @@ char *category=NULL, *value=NULL, *new=NULL; const char *tmp=NULL; struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS }; + FILE *secretfile; + char secretfn[PATH_MAX] = ""; + if (!change_password_realtime(vmu, newpassword)) return; + /* check if we should store the secret in the spool directory next to the messages */ + if (ast_test_flag((&globalflags), VM_SECRETINSPOOL)) { + snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret", VM_SPOOL_DIR, vmu->context, vmu->mailbox); + secretfile = fopen(secretfn, "w"); + if (secretfile) { + if (fprintf(secretfile, "%s", newpassword) < 0) + ast_log (LOG_ERROR, "Error writing voicemail secret to %s\n", secretfn); + else { + if (option_verbose > 3) + ast_verbose( VERBOSE_PREFIX_4 "writing vmsecret to file %s succeeded\n", secretfn); + reset_user_pw(vmu->context, vmu->mailbox, newpassword); + } + fclose(secretfile); + } else { + ast_log (LOG_ERROR, "Error opening voicemail secret file %s\n", secretfn); + } + return; + } + /* check voicemail.conf */ if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) { while ((category = ast_category_browse(cfg, category))) { @@ -9546,6 +9570,7 @@ struct ast_vm_user *vmu; char *mailbox_full; int new = 0, old = 0, urgent = 0; + char secretfn[PATH_MAX] = ""; tmp = ast_strdupa(data); @@ -9566,6 +9591,11 @@ if (stringp && (s = strsep(&stringp, ","))) apply_options(vmu, s); + if (ast_test_flag((&globalflags), VM_SECRETINSPOOL)) { + snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret", VM_SPOOL_DIR, vmu->context, vmu->mailbox); + read_secret_from_file(secretfn, vmu->password, sizeof(vmu->password)); + } + mailbox_full = alloca(strlen(box) + strlen(context) + 1); strcpy(mailbox_full, box); strcat(mailbox_full, "@"); @@ -10237,6 +10267,7 @@ int x; int tmpadsi[4]; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + char secretfn[PATH_MAX] = ""; ast_unload_realtime("voicemail"); ast_unload_realtime("voicemail_data"); @@ -10727,6 +10758,9 @@ if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) val = "no"; ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); + if (!(val = ast_variable_retrieve(cfg, "general", "secretinspool"))) + val = "no"; + ast_set2_flag((&globalflags), ast_true(val), VM_SECRETINSPOOL); poll_freq = DEFAULT_POLL_FREQ; if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) { @@ -10748,6 +10782,10 @@ populate_defaults(current); apply_options_full(current, ast_variable_browse(ucfg, cat)); ast_copy_string(current->context, userscontext, sizeof(current->context)); + if (ast_test_flag((&globalflags), VM_SECRETINSPOOL)) { + snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret", VM_SPOOL_DIR, current->context, current->mailbox); + read_secret_from_file(secretfn, current->password, sizeof(current->password)); + } } } ast_config_destroy(ucfg); @@ -10883,6 +10921,27 @@ return res; } +static void read_secret_from_file(char *secretfn, char *password, int passwordlen) { + FILE *secretfile; + char secrettemp[80]; + + secretfile = fopen(secretfn, "r"); + if (secretfile) { + if (fgets((char *)secrettemp, sizeof(secrettemp), secretfile)) { + ast_copy_string(password, (char *)secrettemp, passwordlen); + if (password[strlen(password)-1] == '\n') + password[strlen(password)-1] = '\0'; + if (option_verbose > 3) + ast_verbose( VERBOSE_PREFIX_4 "reading vmsecret from file %s succeeded\n", secretfn); + } else { + ast_log (LOG_NOTICE, "Error reading voicemail secret from %s, using secret from config file\n", secretfn); + } + fclose(secretfile); + } else { + ast_log (LOG_NOTICE, "Error opening voicemail secret file %s for reading, using secret from config file\n", secretfn); + } +} + static int reload(void) { return load_config(1); Index: configs/voicemail.conf.sample =================================================================== --- configs/voicemail.conf.sample (revision 169203) +++ configs/voicemail.conf.sample (working copy) @@ -260,6 +260,18 @@ ; The default is "no". ; tempgreetwarn=yes ; Remind the user that their temporary greeting is set +;secretinspool=yes ; Usually the voicemail password (vmsecret) is stored in the configuration file + ; This is sometimes annoying as Asterisk does modify the configuration file if user + ; changes its vmsecret. By setting this option to yes, the vmsecret is stored in an + ; external file in the users voicemail spool directy. For example if voicemail is configured + ; for user 1234 in voicemail context default, then the secret will be stored per default + ; in /var/spool/asterisk/voicemail/default/1234/secret + ; If the this option is turned on, but the secret file does not exist, then it reads the + ; vmsecret specified from the configuration file (voicemail.conf or users.conf)(if an + ; vmsecret is defined there). Note: this option is ignored for realtime voiceboxes. + ; Note: Make sure that normal Linux users are not allowed to access asterisk's spool + ; directory. + ; The default is "no". ;messagewrap=no ; Enable next/last message to wrap around to ; first (from last) and last (from first) message ; The default is "no".