[Asterisk-Dev] [patch] Function to check passcode against vmpasscode

Gil Kloepfer astr-dev at kloepfer.org
Wed Jan 18 12:37:02 MST 2006


Okay, here is an updated patch against trunk/8190
asterisk/apps/app_voicemail.c that adds passcode checking for an
already-known passcode to app VMAuthenticate.

I also rewrote much of VMAuthenticate to utilize the Asterisk
arg/option parsing library rather than doing its own parsing.
This makes it easier to add additional options later on if needed.

It works as follows:  If you have a passcode in variable "passvar"
that you want to check against the passcode for mailbox 1234, you
would execute code as follows:

      VMAuthenticate(1234,p(${passvar}))
      GotoIf(${AUTH_STATUS}?good:bad)

The AUTH_STATUS variable is set to 1 for successful, 0 for failed.

I also updated the descriptive text for VMAuthenticate to include these
changes.

Feedback appreciated.  Thanks!

---
Gil Kloepfer
astr-dev at kloepfer.org

-- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here --
--- asterisk/apps/app_voicemail.c.ORIG	2006-01-17 16:04:49.000000000 -0600
+++ asterisk/apps/app_voicemail.c	2006-01-18 13:19:52.000000000 -0600
@@ -353,13 +353,21 @@
 "Authenticate with Voicemail passwords";
 
 static char *descrip_vmauthenticate =
-"  VMAuthenticate([mailbox][@context][|options]): This application behaves the\n"
-"same way as the Authenticate application, but the passwords are taken from\n"
-"voicemail.conf.\n"
-"  If the mailbox is specified, only that mailbox's password will be considered\n"
-"valid. If the mailbox is not specified, the channel variable AUTH_MAILBOX will\n"
-"be set with the authenticated mailbox.\n\n"
+"  VMAuthenticate([mailbox][@context][|options]): This application allows\n"
+"authentication against the passcodes in the voicemail system.\n"
+"  Unless the 'p' option is provided, it normally behaves the same way\n"
+"as the Authenticate application except that the passcodes are taken\n"
+"from the voicemail system.  If the mailbox is specified, only that\n"
+"mailbox's passcode will be considered valid. If the mailbox is not\n"
+"specified, the channel variable AUTH_MAILBOX and AUTH_CONTEXT be set\n"
+"with the authenticated mailbox and context.\n\n"
+"  When the 'p' option is provided, the passcode for the specified\n"
+"mailbox/context is simply checked against the passcode in the\n"
+"voicemail system and AUTH_STATUS is set to 1 for a matched passcode\n"
+"or 0 if the passcodes do not match or the specified mailbox does\n"
+"not exist.\n\n"
 "  Options:\n"
+"    p(passcode) - Provide passcode to check against voicemail system\n"
 "    s - Skip playing the initial prompts.\n";
 
 /* Leave a message */
@@ -5644,48 +5652,117 @@
 	return 0;
 }
 
+enum {
+	OPT_VMA_PASSCHECK =     (1 << 0),
+	OPT_VMA_SILENT =        (1 << 1),
+} vma_option_flags;
+
+enum {
+	OPT_VMA_ARG_PASSCHECK  = 0,
+	OPT_VMA_ARG_ARRAY_SIZE = 1,
+} vma_option_args;
+
+AST_APP_OPTIONS(vma_app_options, {
+	AST_APP_OPTION_ARG('p', OPT_VMA_PASSCHECK, OPT_VMA_ARG_PASSCHECK),
+	AST_APP_OPTION('s', OPT_VMA_SILENT),
+});
+
 static int vmauthenticate(struct ast_channel *chan, void *data)
 {
+
+	char *argv[2], *tmp;
+	int argc;
+	char *opts[OPT_VMA_ARG_ARRAY_SIZE];
+	struct ast_flags flags = { 0 };
+	char *vmpass;
 	struct localuser *u;
-	char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
-	struct ast_vm_user vmus;
-	char *options = NULL;
-	int silent = 0, skipuser = 0;
-	int res = -1;
+	struct ast_vm_user vmus, *vmu = NULL;
+
+	int silent = 0;
+	int skipuser = 0;
+	char *passprovided = NULL;
+	char mailbox[AST_MAX_EXTENSION];
+	char *context = NULL;
 
 	LOCAL_USER_ADD(u);
-	
-	if (s) {
-		s = ast_strdupa(s);
-		if (!s) {
-			ast_log(LOG_ERROR, "Out of memory\n");
-			return -1;
+
+	/* Parse arguments and options */
+
+	mailbox[0] = '\0';
+
+	if (!ast_strlen_zero(data)) {
+		tmp = ast_strdupa(data);
+		argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
+
+		/* parse optional mailbox at context */
+		if (argc >= 1 ) {
+			if (!ast_strlen_zero(argv[0])) {
+				/* Parse off context first so mailbox copy doesn't include context */
+				context = strchr(argv[0], '@');
+				if (context)
+					*context++ = '\0';
+
+				ast_copy_string(mailbox, argv[0], sizeof(mailbox));
+			}
 		}
-		user = strsep(&s, "|");
-		options = strsep(&s, "|");
-		if (user) {
-			s = user;
-			user = strsep(&s, "@");
-			context = strsep(&s, "");
-			if (!ast_strlen_zero(user))
-				skipuser++;
-			ast_copy_string(mailbox, user, sizeof(mailbox));
+
+		if (!ast_strlen_zero(mailbox))
+			skipuser++;
+
+		/* parse optional args */
+		if (argc == 2) {
+			if (ast_app_parse_options(vma_app_options, &flags, opts, argv[1]))
+				goto error;
+
+			if (ast_test_flag(&flags, OPT_VMA_SILENT))
+				silent++;
+
+			if (ast_test_flag(&flags, OPT_VMA_PASSCHECK)) {
+				if (ast_strlen_zero(mailbox)) {
+					ast_log(LOG_WARNING, "Checking pre-provided password requires a mailbox\n");
+					goto error;
+				}
+				passprovided = opts[OPT_VMA_ARG_PASSCHECK];
+				if (passprovided == NULL || ast_strlen_zero(passprovided)) {
+					ast_log(LOG_WARNING, "Password check requested but no password provided\n");
+					goto error;
+				}
+			}
 		}
 	}
 
-	if (options) {
-		silent = (strchr(options, 's')) != NULL;
-	}
-
-	if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
-		pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
-		pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
-		ast_play_and_wait(chan, "auth-thankyou");
-		res = 0;
+	/*
+	 * If we're providing a pre-provided password, use a VERY silent
+	 * method of verifying the password.  Otherwise, authenticate using
+	 * vm_authenticate, which requests the info from the caller.
+	 */
+
+	if (passprovided) {
+		pbx_builtin_setvar_helper(chan, "AUTH_STATUS", "0");
+		vmu = find_user(&vmus, context, mailbox);
+		if (vmu) {
+			vmpass = vmu->password;
+			if (*vmpass == '-')
+				vmpass++;
+
+			if (*vmpass != '\0' && strcmp(passprovided, vmpass) == 0)
+				pbx_builtin_setvar_helper(chan, "AUTH_STATUS", "1");
+		}
+	} else {
+		if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
+			pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
+			pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
+			ast_play_and_wait(chan, "auth-thankyou");
+		} else
+			goto error;
 	}
 
 	LOCAL_USER_REMOVE(u);
-	return res;
+	return 0;
+
+error:
+	LOCAL_USER_REMOVE(u);
+	return -1;
 }
 
 static char show_voicemail_users_help[] =
-- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here --



More information about the asterisk-dev mailing list