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