--- asterisk-1.4.22/configs/voicemail.conf.sample 2008-05-14 22:43:08.000000000 +0200 +++ asterisk-1.4.22-patched/configs/voicemail.conf.sample 2009-01-19 14:37:03.000000000 +0100 @@ -215,6 +215,17 @@ ; hidefromdir=yes ; Hide this mailbox from the directory produced by app_directory ; 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 in 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). + ; The default is "no". + [zonemessages] eastern=America/New_York|'vm-received' Q 'digits/at' IMp --- asterisk-1.4.22/apps/app_voicemail.c 2008-09-05 18:35:54.000000000 +0200 +++ asterisk-1.4.22-patched/apps/app_voicemail.c 2009-01-19 16:06:09.000000000 +0100 @@ -200,6 +200,7 @@ #define VM_ALLOCED (1 << 13) #define VM_SEARCH (1 << 14) #define VM_TEMPGREETWARN (1 << 15) /*!< Remind user tempgreeting is set */ +#define VM_SECRETINSPOOL (1 << 16) /*!< vmsecret is read/write to voicemail directory instead of config file */ #define ERROR_LOCK_PATH -100 #define ERROR_MAILBOX_FULL -200 @@ -397,6 +398,7 @@ static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit); #endif static void apply_options(struct ast_vm_user *vmu, const char *options); +static void read_secret_from_file(char *secretfn, char *password, int passwordlen); #ifdef ODBC_STORAGE static char odbc_database[80]; @@ -812,10 +814,31 @@ struct ast_category *cat=NULL; char *category=NULL, *value=NULL, *new=NULL; const char *tmp=NULL; + 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_with_comments(VOICEMAIL_CONFIG))) { while ((category = ast_category_browse(cfg, category))) { @@ -7641,6 +7664,7 @@ char *stringp; char *s; struct ast_vm_user *vmu; + char secretfn[PATH_MAX] = ""; tmp = ast_strdupa(data); @@ -7658,6 +7682,10 @@ ast_copy_string(vmu->pager, s, sizeof(vmu->pager)); 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)); + } } return 0; } @@ -7935,6 +7963,7 @@ const char *volgainstr; int x; int tmpadsi[4]; + char secretfn[PATH_MAX] = ""; cfg = ast_config_load(VOICEMAIL_CONFIG); @@ -8286,6 +8315,8 @@ if (!(astdirfwd = ast_variable_retrieve(cfg, "general", "usedirectory"))) astdirfwd = "no"; ast_set2_flag((&globalflags), ast_true(astdirfwd), VM_DIRECFORWARD); + if ((s = ast_variable_retrieve(cfg, "general", "secretinspool"))) + ast_set2_flag((&globalflags), ast_true(s), VM_SECRETINSPOOL); if ((ucfg = ast_config_load("users.conf"))) { for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail"))) @@ -8294,6 +8325,10 @@ populate_defaults(cur); apply_options_full(cur, ast_variable_browse(ucfg, cat)); ast_copy_string(cur->context, userscontext, sizeof(cur->context)); + if (ast_test_flag((&globalflags), VM_SECRETINSPOOL)) { + snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret", VM_SPOOL_DIR, cur->context, cur->mailbox); + read_secret_from_file(secretfn, cur->password, sizeof(cur->password)); + } } } ast_config_destroy(ucfg); @@ -8498,15 +8533,15 @@ if (res) return(res); + /* compute the location of the voicemail spool directory */ + snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR); + if ((res=load_config())) { return(res); } ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry)); - /* compute the location of the voicemail spool directory */ - snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR); - ast_install_vm_functions(has_voicemail, inboxcount, messagecount); return res; @@ -8764,6 +8799,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 play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir, signed char record_gain, struct vm_state *vms)