In case anybody is interested, here's a patch to store voicemail
passwords as an md5sum in the astdb. Change the first character
of the password field in voicemail.conf to a '!' in order to use.
-Tilghman
Index: apps/app_voicemail.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_voicemail.c,v
retrieving revision 1.79
diff -c -r1.79 app_voicemail.c
*** apps/app_voicemail.c 6 Mar 2003 17:17:38 -0000 1.79
--- apps/app_voicemail.c 17 Mar 2003 22:26:20 -0000
***************
*** 23,28 ****
--- 23,29 ----
#include <asterisk/adsi.h>
#include <asterisk/app.h>
#include <asterisk/manager.h>
+ #include <asterisk/astdb.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
***************
*** 32,37 ****
--- 33,39 ----
#include <sys/time.h>
#include <sys/stat.h>
#include <time.h>
+ #include <openssl/md5.h>
#include <pthread.h>
#include "../asterisk.h"
***************
*** 125,201 ****
static int vm_change_password(char *username, char *password, char *newpassword)
{
! /* There's probably a better way of doing this. */
! /* That's why I've put the password change in a separate function. */
! FILE *configin;
! FILE *configout;
! char inbuf[256];
! char orig[256];
! char tmpin[AST_CONFIG_MAX_PATH];
! char tmpout[AST_CONFIG_MAX_PATH];
! char *user, *pass, *rest, *trim;
snprintf((char *)tmpin, sizeof(tmpin)-1, "%s/voicemail.conf",(char *)ast_config_AST_CONFIG_DIR);
snprintf((char *)tmpout, sizeof(tmpout)-1, "%s/voicemail.conf.new",(char *)ast_config_AST_CONFIG_DIR);
! configin = fopen((char *)tmpin,"r");
! configout = fopen((char *)tmpout,"w+");
! while (!feof(configin)) {
! /* Read in the line */
! fgets(inbuf, sizeof(inbuf), configin);
! if (!feof(configin)) {
! /* Make a backup of it */
! memcpy(orig, inbuf, sizeof(orig));
! /* Strip trailing \n and comment */
! inbuf[strlen(inbuf) - 1] = '\0';
! user = strchr(inbuf, ';');
! if (user)
! *user = '\0';
! user=inbuf;
! while(*user < 33)
! user++;
! pass = strchr(user, '=');
! if (pass > user) {
! trim = pass - 1;
! while(*trim && *trim < 33) {
! *trim = '\0';
! trim--;
! }
}
! if (pass) {
! *pass = '\0';
pass++;
! if (*pass == '>')
! pass++;
! while(*pass && *pass < 33)
! pass++;
}
! if (pass) {
! rest = strchr(pass,',');
! if (rest) {
! *rest = '\0';
! rest++;
! }
! } else
! rest = NULL;
! if (user && pass && *user && *pass && !strcmp(user, username) && !strcmp(pass, password)) {
! /* This is the line */
! if (rest) {
! fprintf(configout, "%s => %s,%s\n", username,newpassword,rest);
! } else {
! fprintf(configout, "%s => %s\n", username,newpassword);
! }
} else {
! /* Put it back like it was */
! fprintf(configout, orig);
}
}
! }
! fclose(configin);
! fclose(configout);
! unlink((char *)tmpin);
! rename((char *)tmpout,(char *)tmpin);
return(1);
}
--- 127,220 ----
static int vm_change_password(char *username, char *password, char *newpassword)
{
! /* There's probably a better way of doing this. */
! /* That's why I've put the password change in a separate function. */
! FILE *configin;
! FILE *configout;
! char inbuf[256];
! char orig[256];
! char tmpin[AST_CONFIG_MAX_PATH];
! char tmpout[AST_CONFIG_MAX_PATH];
! char *user, *pass, *rest, *trim;
snprintf((char *)tmpin, sizeof(tmpin)-1, "%s/voicemail.conf",(char *)ast_config_AST_CONFIG_DIR);
snprintf((char *)tmpout, sizeof(tmpout)-1, "%s/voicemail.conf.new",(char *)ast_config_AST_CONFIG_DIR);
! configin = fopen((char *)tmpin,"r");
! configout = fopen((char *)tmpout,"w+");
! while (!feof(configin)) {
! /* Read in the line */
! fgets(inbuf, sizeof(inbuf), configin);
! if (!feof(configin)) {
! /* Make a backup of it */
! memcpy(orig, inbuf, sizeof(orig));
! /* Strip trailing \n and comment */
! inbuf[strlen(inbuf) - 1] = '\0';
! user = strchr(inbuf, ';');
! if (user)
! *user = '\0';
! user=inbuf;
! /* Leading spaces and/or control characters */
! while(*user < 33)
! user++;
! pass = strchr(user, '=');
! if (pass > user) {
! trim = pass - 1;
! while(*trim && *trim < 33) {
! *trim = '\0';
! trim--;
}
! }
! if (pass) {
! *pass = '\0';
! pass++;
! if (*pass == '>')
pass++;
! while(*pass && *pass < 33)
! pass++;
! }
! if (pass) {
! rest = strchr(pass,',');
! if (rest) {
! *rest = '\0';
! rest++;
}
! } else
! rest = NULL;
! if (user && pass && *user && *pass && !strcmp(user, username) && !strcmp(pass, password)) {
! /* This is the line */
! if (rest) {
! fprintf(configout, "%s => %s,%s\n", username,newpassword,rest);
} else {
! fprintf(configout, "%s => %s\n", username,newpassword);
}
+ } else if (user && pass && *user && *pass && !strcmp(user, username) && !strcmp(pass, "!")) {
+ /* We want MD5 passwords */
+ char passkey[80] = "password/";
+ unsigned char passval[17];
+ /* Can't store raw MD5, as it could have a valid 00 in the middle */
+ char passval_hex[33];
+ int i;
+
+ fprintf(configout, orig);
+
+ strncpy(passkey + strnlen(passkey,80), user, 80 - strnlen(passkey,80));
+ MD5(newpassword,strlen(newpassword),passval);
+ for (i=0;i<16;i++)
+ sprintf(passval_hex + i * 2, "%02x", (int)passval[i]);
+ passval_hex[32] = '\0';
+ ast_db_put("vm",passkey,passval_hex);
+ } else {
+ /* Put it back like it was */
+ fprintf(configout, orig);
}
! }
! }
! fclose(configin);
! fclose(configout);
! unlink((char *)tmpin);
! rename((char *)tmpout,(char *)tmpin);
return(1);
}
***************
*** 1815,1821 ****
copy = strdup(copy);
stringp=copy;
strsep(&stringp, ",");
! if (!strcmp(password,copy))
valid++;
else {
if (option_verbose > 2)
--- 1834,1864 ----
copy = strdup(copy);
stringp=copy;
strsep(&stringp, ",");
! /* Is the password no longer stored in voicemail.conf? */
! if (!strncmp("!",copy,1)) {
! char passkey[80] = "password/";
! unsigned char passhash[33];
!
! /* password/<exten> */
! strncpy(passkey + strnlen(passkey,80),username,80 - strnlen(passkey,80));
! if (!ast_db_get("vm",passkey,passhash,33)) {
! unsigned char checkhash[17];
! char checkhash_hex[33];
! int i;
!
! MD5(password,strlen(password),checkhash);
! /* Can't compare raw MD5 because it could have a valid 00 in the middle */
! for (i=0;i<16;i++) {
! sprintf(checkhash_hex + i * 2,"%02x",(int)checkhash[i]);
! }
! checkhash_hex[32] = '\0';
! if (!strcmp(passhash,checkhash_hex))
! valid++;
! } else {
! ast_log(LOG_WARNING, "Unable to read crypted password\n");
! goto out;
! }
! } else if (!strcmp(password,copy))
valid++;
else {
if (option_verbose > 2)