From 555e7e7a5b9fb6bb1ae87678ee74a06af23088f9 Mon Sep 17 00:00:00 2001 From: mogorman Date: Thu, 5 Jan 2006 21:47:44 +0000 Subject: Added feature from bug #5053, allowing for app_authenticate to set a max number of digits also implemented the new argument and option parsing code. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@7822 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_authenticate.c | 99 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 30 deletions(-) (limited to 'apps/app_authenticate.c') diff --git a/apps/app_authenticate.c b/apps/app_authenticate.c index 274aec48c..b7678a002 100644 --- a/apps/app_authenticate.c +++ b/apps/app_authenticate.c @@ -44,6 +44,23 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/app.h" #include "asterisk/astdb.h" #include "asterisk/utils.h" +#include "asterisk/options.h" + +enum { + OPT_ACCOUNT = (1 << 0), + OPT_DATABASE = (1 << 1), + OPT_JUMP = (1 << 2), + OPT_MULTIPLE = (1 << 3), + OPT_REMOVE = (1 << 4), +} auth_option_flags; + +AST_APP_OPTIONS(auth_app_options, { + AST_APP_OPTION('a', OPT_ACCOUNT), + AST_APP_OPTION('d', OPT_DATABASE), + AST_APP_OPTION('j', OPT_JUMP), + AST_APP_OPTION('m', OPT_MULTIPLE), + AST_APP_OPTION('r', OPT_REMOVE), +}); static char *tdesc = "Authentication Application"; @@ -52,9 +69,9 @@ static char *app = "Authenticate"; static char *synopsis = "Authenticate a user"; static char *descrip = -" Authenticate(password[|options]): This application asks the caller to enter a\n" -"given password in order to continue dialplan execution. If the password begins\n" -"with the '/' character, it is interpreted as a file which contains a list of\n" +" Authenticate(password[|options[|maxdigits]]): This application asks the caller\n" +"to enter a given password in order to continue dialplan execution. If the password\n" +"begins with the '/' character, it is interpreted as a file which contains a list of\n" "valid passwords, listed 1 password per line in the file.\n" " When using a database key, the value associated with the key can be anything.\n" "Users have three attempts to authenticate before the channel is hung up. If the\n" @@ -69,6 +86,10 @@ static char *descrip = " the file. When one of the passwords is matched, the channel will have\n" " its account code set to the corresponding account code in the file.\n" " r - Remove the database key upon successful entry (valid with 'd' only)\n" +" maxdigits - maximum acceptable number of digits. Stops reading after\n" +" maxdigits have been entered (without requiring the user to\n" +" press the '#' key).\n" +" Defaults to 0 - no limit - wait for the user press the '#' key.\n" ; STANDARD_LOCAL_USER; @@ -78,13 +99,19 @@ LOCAL_USER_DECL; static int auth_exec(struct ast_channel *chan, void *data) { int res=0; - int jump = 0; int retries; struct localuser *u; - char password[256]=""; char passwd[256]; - char *opts; char *prompt; + int maxdigits; + char *argcopy =NULL; + struct ast_flags flags = {0}; + + AST_DECLARE_APP_ARGS(arglist, + AST_APP_ARG(password); + AST_APP_ARG(options); + AST_APP_ARG(maxdigits); + ); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n"); @@ -101,37 +128,49 @@ static int auth_exec(struct ast_channel *chan, void *data) } } - strncpy(password, data, sizeof(password) - 1); - opts=strchr(password, '|'); - if (opts) { - *opts = 0; - opts++; - } else - opts = ""; - if (strchr(opts, 'j')) - jump = 1; + argcopy = ast_strdupa(data); + if (!argcopy) { + ast_log(LOG_ERROR, "Out of memory!\n"); + LOCAL_USER_REMOVE(u); + return -1; + } + + AST_STANDARD_APP_ARGS(arglist,argcopy); + + if (!ast_strlen_zero(arglist.options)) { + ast_app_parse_options(auth_app_options, &flags, NULL, arglist.options); + } + + if (!ast_strlen_zero(arglist.maxdigits)) { + maxdigits = atoi(arglist.maxdigits); + if ((maxdigits<1) || (maxdigits>sizeof(passwd)-2)) + maxdigits = sizeof(passwd) - 2; + } else { + maxdigits = sizeof(passwd) - 2; + } + /* Start asking for password */ prompt = "agent-pass"; for (retries = 0; retries < 3; retries++) { - res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0); + res = ast_app_getdata(chan, prompt, passwd, maxdigits, 0); if (res < 0) break; res = 0; - if (password[0] == '/') { - if (strchr(opts, 'd')) { + if (arglist.password[0] == '/') { + if (ast_test_flag(&flags,OPT_DATABASE)) { char tmp[256]; /* Compare against a database key */ - if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) { + if (!ast_db_get(arglist.password + 1, passwd, tmp, sizeof(tmp))) { /* It's a good password */ - if (strchr(opts, 'r')) { - ast_db_del(password + 1, passwd); + if (ast_test_flag(&flags,OPT_REMOVE)) { + ast_db_del(arglist.password + 1, passwd); } break; } } else { /* Compare against a file */ FILE *f; - f = fopen(password, "r"); + f = fopen(arglist.password, "r"); if (f) { char buf[256] = ""; char md5passwd[33] = ""; @@ -141,7 +180,7 @@ static int auth_exec(struct ast_channel *chan, void *data) fgets(buf, sizeof(buf), f); if (!feof(f) && !ast_strlen_zero(buf)) { buf[strlen(buf) - 1] = '\0'; - if (strchr(opts, 'm')) { + if (ast_test_flag(&flags,OPT_MULTIPLE)) { md5secret = strchr(buf, ':'); if (md5secret == NULL) continue; @@ -149,13 +188,13 @@ static int auth_exec(struct ast_channel *chan, void *data) md5secret++; ast_md5_hash(md5passwd, passwd); if (!strcmp(md5passwd, md5secret)) { - if (strchr(opts, 'a')) + if (ast_test_flag(&flags,OPT_ACCOUNT)) ast_cdr_setaccount(chan, buf); break; } } else { if (!strcmp(passwd, buf)) { - if (strchr(opts, 'a')) + if (ast_test_flag(&flags,OPT_ACCOUNT)) ast_cdr_setaccount(chan, buf); break; } @@ -164,7 +203,7 @@ static int auth_exec(struct ast_channel *chan, void *data) } fclose(f); if (!ast_strlen_zero(buf)) { - if (strchr(opts, 'm')) { + if (ast_test_flag(&flags,OPT_MULTIPLE)) { if (md5secret && !strcmp(md5passwd, md5secret)) break; } else { @@ -173,23 +212,23 @@ static int auth_exec(struct ast_channel *chan, void *data) } } } else - ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno)); + ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", arglist.password, strerror(errno)); } } else { /* Compare against a fixed password */ - if (!strcmp(passwd, password)) + if (!strcmp(passwd, arglist.password)) break; } prompt="auth-incorrect"; } if ((retries < 3) && !res) { - if (strchr(opts, 'a') && !strchr(opts, 'm')) + if (ast_test_flag(&flags,OPT_ACCOUNT) && !ast_test_flag(&flags,OPT_MULTIPLE)) ast_cdr_setaccount(chan, passwd); res = ast_streamfile(chan, "auth-thankyou", chan->language); if (!res) res = ast_waitstream(chan, ""); } else { - if (jump && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) { + if (ast_test_flag(&flags,OPT_JUMP) && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) { res = 0; } else { if (!ast_streamfile(chan, "vm-goodbye", chan->language)) -- cgit v1.2.3