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: https://origsvn.digium.com/svn/asterisk/trunk@7822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Matt O'Gorman
2006-01-05 21:47:44 +00:00
parent 6ac09042f1
commit 8adf708c1b

View File

@@ -44,6 +44,23 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h" #include "asterisk/app.h"
#include "asterisk/astdb.h" #include "asterisk/astdb.h"
#include "asterisk/utils.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"; static char *tdesc = "Authentication Application";
@@ -52,9 +69,9 @@ static char *app = "Authenticate";
static char *synopsis = "Authenticate a user"; static char *synopsis = "Authenticate a user";
static char *descrip = static char *descrip =
" Authenticate(password[|options]): This application asks the caller to enter a\n" " Authenticate(password[|options[|maxdigits]]): This application asks the caller\n"
"given password in order to continue dialplan execution. If the password begins\n" "to enter a given password in order to continue dialplan execution. If the password\n"
"with the '/' character, it is interpreted as a file which contains a list of\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" "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" " 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" "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" " 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" " 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" " 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; STANDARD_LOCAL_USER;
@@ -78,13 +99,19 @@ LOCAL_USER_DECL;
static int auth_exec(struct ast_channel *chan, void *data) static int auth_exec(struct ast_channel *chan, void *data)
{ {
int res=0; int res=0;
int jump = 0;
int retries; int retries;
struct localuser *u; struct localuser *u;
char password[256]="";
char passwd[256]; char passwd[256];
char *opts;
char *prompt; 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)) { if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n"); 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); argcopy = ast_strdupa(data);
opts=strchr(password, '|'); if (!argcopy) {
if (opts) { ast_log(LOG_ERROR, "Out of memory!\n");
*opts = 0; LOCAL_USER_REMOVE(u);
opts++; return -1;
} else }
opts = "";
if (strchr(opts, 'j')) AST_STANDARD_APP_ARGS(arglist,argcopy);
jump = 1;
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 */ /* Start asking for password */
prompt = "agent-pass"; prompt = "agent-pass";
for (retries = 0; retries < 3; retries++) { 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) if (res < 0)
break; break;
res = 0; res = 0;
if (password[0] == '/') { if (arglist.password[0] == '/') {
if (strchr(opts, 'd')) { if (ast_test_flag(&flags,OPT_DATABASE)) {
char tmp[256]; char tmp[256];
/* Compare against a database key */ /* 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 */ /* It's a good password */
if (strchr(opts, 'r')) { if (ast_test_flag(&flags,OPT_REMOVE)) {
ast_db_del(password + 1, passwd); ast_db_del(arglist.password + 1, passwd);
} }
break; break;
} }
} else { } else {
/* Compare against a file */ /* Compare against a file */
FILE *f; FILE *f;
f = fopen(password, "r"); f = fopen(arglist.password, "r");
if (f) { if (f) {
char buf[256] = ""; char buf[256] = "";
char md5passwd[33] = ""; char md5passwd[33] = "";
@@ -141,7 +180,7 @@ static int auth_exec(struct ast_channel *chan, void *data)
fgets(buf, sizeof(buf), f); fgets(buf, sizeof(buf), f);
if (!feof(f) && !ast_strlen_zero(buf)) { if (!feof(f) && !ast_strlen_zero(buf)) {
buf[strlen(buf) - 1] = '\0'; buf[strlen(buf) - 1] = '\0';
if (strchr(opts, 'm')) { if (ast_test_flag(&flags,OPT_MULTIPLE)) {
md5secret = strchr(buf, ':'); md5secret = strchr(buf, ':');
if (md5secret == NULL) if (md5secret == NULL)
continue; continue;
@@ -149,13 +188,13 @@ static int auth_exec(struct ast_channel *chan, void *data)
md5secret++; md5secret++;
ast_md5_hash(md5passwd, passwd); ast_md5_hash(md5passwd, passwd);
if (!strcmp(md5passwd, md5secret)) { if (!strcmp(md5passwd, md5secret)) {
if (strchr(opts, 'a')) if (ast_test_flag(&flags,OPT_ACCOUNT))
ast_cdr_setaccount(chan, buf); ast_cdr_setaccount(chan, buf);
break; break;
} }
} else { } else {
if (!strcmp(passwd, buf)) { if (!strcmp(passwd, buf)) {
if (strchr(opts, 'a')) if (ast_test_flag(&flags,OPT_ACCOUNT))
ast_cdr_setaccount(chan, buf); ast_cdr_setaccount(chan, buf);
break; break;
} }
@@ -164,7 +203,7 @@ static int auth_exec(struct ast_channel *chan, void *data)
} }
fclose(f); fclose(f);
if (!ast_strlen_zero(buf)) { if (!ast_strlen_zero(buf)) {
if (strchr(opts, 'm')) { if (ast_test_flag(&flags,OPT_MULTIPLE)) {
if (md5secret && !strcmp(md5passwd, md5secret)) if (md5secret && !strcmp(md5passwd, md5secret))
break; break;
} else { } else {
@@ -173,23 +212,23 @@ static int auth_exec(struct ast_channel *chan, void *data)
} }
} }
} else } 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 { } else {
/* Compare against a fixed password */ /* Compare against a fixed password */
if (!strcmp(passwd, password)) if (!strcmp(passwd, arglist.password))
break; break;
} }
prompt="auth-incorrect"; prompt="auth-incorrect";
} }
if ((retries < 3) && !res) { 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); ast_cdr_setaccount(chan, passwd);
res = ast_streamfile(chan, "auth-thankyou", chan->language); res = ast_streamfile(chan, "auth-thankyou", chan->language);
if (!res) if (!res)
res = ast_waitstream(chan, ""); res = ast_waitstream(chan, "");
} else { } 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; res = 0;
} else { } else {
if (!ast_streamfile(chan, "vm-goodbye", chan->language)) if (!ast_streamfile(chan, "vm-goodbye", chan->language))