[asterisk-commits] tilghman: trunk r115582 - in /trunk: ./ apps/ configs/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri May 9 12:28:07 CDT 2008
Author: tilghman
Date: Fri May 9 12:28:06 2008
New Revision: 115582
URL: http://svn.digium.com/view/asterisk?view=rev&rev=115582
Log:
Allow a password change to be validated by an external script.
(closes issue #12090)
Reported by: jaroth
Patches:
vm-check-newpassword.diff.txt uploaded by mvanbaak (license 7)
20080509__bug12090.diff.txt uploaded by Corydon76 (license 14)
Modified:
trunk/CHANGES
trunk/apps/app_voicemail.c
trunk/configs/voicemail.conf.sample
Modified: trunk/CHANGES
URL: http://svn.digium.com/view/asterisk/trunk/CHANGES?view=diff&rev=115582&r1=115581&r2=115582
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Fri May 9 12:28:06 2008
@@ -42,6 +42,11 @@
quite helpful.
* Voicemail now permits a mailbox setting to wrap around from first to last
messages, if the "messagewrap" option is set to a true value.
+ * Voicemail now permits an external script to be run, for password validation.
+ The script should output "VALID" or "INVALID" on stdout, depending upon the
+ wish to validate or invalidate the password given. Arguments are:
+ "mailbox" "context" "oldpass" "newpass". See the sample voicemail.conf for
+ more details
* Dial has a new option: F(context^extension^pri), which permits a callee to
continue in the dialplan, at the specified label, if the caller hangs up.
* ChanSpy and ExtenSpy have a new option, 's' which suppresses speaking the
Modified: trunk/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/trunk/apps/app_voicemail.c?view=diff&rev=115582&r1=115581&r2=115582
==============================================================================
--- trunk/apps/app_voicemail.c (original)
+++ trunk/apps/app_voicemail.c Fri May 9 12:28:06 2008
@@ -201,6 +201,8 @@
#define MAXMSG 100
#define MAXMSGLIMIT 9999
+
+#define MINPASSWORD 0 /*!< Default minimum mailbox password length */
#define BASELINELEN 72
#define BASEMAXINLINE 256
@@ -472,6 +474,7 @@
static char VM_SPOOL_DIR[PATH_MAX];
static char ext_pass_cmd[128];
+static char ext_pass_check_cmd[128];
int my_umask;
@@ -587,6 +590,7 @@
static int maxgreet;
static int skipms;
static int maxlogins;
+static int minpassword;
/*! Poll mailboxes for changes since there is something external to
* app_voicemail that may change them. */
@@ -645,6 +649,7 @@
static char vm_passchanged[80] = "vm-passchanged";
static char vm_reenterpassword[80] = "vm-reenterpassword";
static char vm_mismatch[80] = "vm-mismatch";
+static char vm_invalid_password[80] = "vm-invalid-password";
static struct ast_flags globalflags = {0};
@@ -820,6 +825,85 @@
} else if (!strcasecmp(var, "options")) {
apply_options(vmu, value);
}
+}
+
+static char *vm_check_password_shell(char *command, char *buf, size_t len)
+{
+ int fds[2], pid = 0;
+
+ memset(buf, 0, len);
+
+ if (pipe(fds)) {
+ snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
+ } else {
+ /* good to go*/
+ pid = ast_safe_fork(0);
+
+ if (pid < 0) {
+ /* ok maybe not */
+ close(fds[0]);
+ close(fds[1]);
+ snprintf(buf, len, "FAILURE: Fork failed");
+ } else if (pid) {
+ /* parent */
+ close(fds[1]);
+ read(fds[0], buf, len);
+ close(fds[0]);
+ } else {
+ /* child */
+ AST_DECLARE_APP_ARGS(arg,
+ AST_APP_ARG(v)[20];
+ );
+ char *mycmd = ast_strdupa(command);
+
+ close(fds[0]);
+ dup2(fds[1], STDOUT_FILENO);
+ close(fds[1]);
+ ast_close_fds_above_n(STDOUT_FILENO);
+
+ AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
+
+ execv(arg.v[0], arg.v);
+ printf("FAILURE: %s", strerror(errno));
+ _exit(0);
+ }
+ }
+ return buf;
+}
+
+/*!
+ * \brief Check that password meets minimum required length
+ * \param vmu The voicemail user to change the password for.
+ * \param password The password string to check
+ *
+ * \return zero on ok, 1 on not ok.
+ */
+static int check_password(struct ast_vm_user *vmu, char *password)
+{
+ /* check minimum length */
+ if (strlen(password) < minpassword)
+ return 1;
+ if (!ast_strlen_zero(ext_pass_check_cmd)) {
+ char cmd[255], buf[255];
+
+ ast_log(LOG_DEBUG, "Verify password policies for %s\n", password);
+
+ snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
+ if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
+ ast_debug(5, "Result: %s\n", buf);
+ if (!strncasecmp(buf, "VALID", 5)) {
+ ast_debug(3, "Passed password check: '%s'\n", buf);
+ return 0;
+ } else if (!strncasecmp(buf, "FAILURE", 7)) {
+ ast_log(LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
+ return 0;
+ } else {
+ ast_log(LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
+ return 1;
+ }
+ }
+ }
+ return 0;
}
/*!
@@ -7121,19 +7205,25 @@
cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
if (cmd < 0 || cmd == 't' || cmd == '#')
return cmd;
- newpassword2[1] = '\0';
- newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
- if (cmd == '#')
- newpassword2[0] = '\0';
- if (cmd < 0 || cmd == 't' || cmd == '#')
- return cmd;
- cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
- if (cmd < 0 || cmd == 't' || cmd == '#')
- return cmd;
- if (!strcmp(newpassword, newpassword2))
- break;
- ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
- cmd = ast_play_and_wait(chan, vm_mismatch);
+ cmd = check_password(vmu, newpassword); /* perform password validation */
+ if (cmd != 0) {
+ ast_log(LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
+ cmd = ast_play_and_wait(chan, vm_invalid_password);
+ } else {
+ newpassword2[1] = '\0';
+ newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
+ if (cmd == '#')
+ newpassword2[0] = '\0';
+ if (cmd < 0 || cmd == 't' || cmd == '#')
+ return cmd;
+ cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
+ if (cmd < 0 || cmd == 't' || cmd == '#')
+ return cmd;
+ if (!strcmp(newpassword, newpassword2))
+ break;
+ ast_log(LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
+ cmd = ast_play_and_wait(chan, vm_mismatch);
+ }
if (++tries == 3)
return -1;
}
@@ -7252,6 +7342,12 @@
if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
break;
}
+ }
+ cmd = check_password(vmu, newpassword); /* perform password validation */
+ if (cmd != 0) {
+ ast_log(LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
+ cmd = ast_play_and_wait(chan, vm_invalid_password);
+ break;
}
newpassword2[1] = '\0';
newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
@@ -9003,6 +9099,7 @@
AST_LIST_UNLOCK(&zones);
memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
+ memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
if (cfg) {
/* General settings */
@@ -9089,6 +9186,12 @@
} else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
+ }
+
+ /* External password validation command */
+ if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
+ ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
+ ast_log(LOG_DEBUG, "found externpasscheck: %s\n", ext_pass_check_cmd);
}
#ifdef IMAP_STORAGE
@@ -9277,6 +9380,15 @@
}
}
+ minpassword = MINPASSWORD;
+ if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
+ if (sscanf(val, "%d", &x) == 1) {
+ minpassword = x;
+ } else {
+ ast_log(LOG_WARNING, "Invalid minimum password length. Default to %d\n", minpassword);
+ }
+ }
+
/* Force new user to record name ? */
if (!(val = ast_variable_retrieve(cfg, "general", "forcename")))
val = "no";
@@ -9399,6 +9511,8 @@
ast_copy_string(vm_password, val, sizeof(vm_password));
if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
+ if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
+ ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
Modified: trunk/configs/voicemail.conf.sample
URL: http://svn.digium.com/view/asterisk/trunk/configs/voicemail.conf.sample?view=diff&rev=115582&r1=115581&r2=115582
==============================================================================
--- trunk/configs/voicemail.conf.sample (original)
+++ trunk/configs/voicemail.conf.sample Fri May 9 12:28:06 2008
@@ -78,6 +78,13 @@
; the externpassnotify option below instead.
;externpass=/usr/bin/myapp
;externpassnotify=/usr/bin/myapp
+
+; If you need to have an external program, i.e. /usr/bin/myapp
+; called when a user changes her voicemail password, uncomment this:
+;externpasscheck=/usr/bin/myapp
+; Arguments for this script are:
+; mailbox context oldpass newpass
+
; For the directory, you can override the intro file if you want
;directoryintro=dir-intro
; The character set for voicemail messages can be specified here
@@ -245,6 +252,7 @@
;messagewrap=no ; Enable next/last message to wrap around to
; first (from last) and last (from first) message
; The default is "no".
+; minpassword=0 ; Enforce minimum password length
; vm-password=custom_sound
; Customize which sound file is used instead of the default
@@ -264,6 +272,9 @@
; Customize which sound file is used instead of the default
; prompt that says: "The passwords you entered and re-entered
; did not match. Please try again."
+; vm-invalid-password=custom_sound
+ ; Customize which sound file is used instead of the default
+ ; prompt that says: ...
; listen-control-forward-key=# ; Customize the key that fast-forwards message playback
; listen-control-reverse-key=* ; Customize the key that rewinds message playback
; listen-control-pause-key=0 ; Customize the key that pauses/unpauses message playback
More information about the asterisk-commits
mailing list