mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	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:
		| @@ -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)) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user