00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00035
00036 #include "asterisk/lock.h"
00037 #include "asterisk/file.h"
00038 #include "asterisk/channel.h"
00039 #include "asterisk/pbx.h"
00040 #include "asterisk/module.h"
00041 #include "asterisk/app.h"
00042 #include "asterisk/astdb.h"
00043 #include "asterisk/utils.h"
00044
00045 enum {
00046 OPT_ACCOUNT = (1 << 0),
00047 OPT_DATABASE = (1 << 1),
00048 OPT_MULTIPLE = (1 << 3),
00049 OPT_REMOVE = (1 << 4),
00050 };
00051
00052 AST_APP_OPTIONS(auth_app_options, {
00053 AST_APP_OPTION('a', OPT_ACCOUNT),
00054 AST_APP_OPTION('d', OPT_DATABASE),
00055 AST_APP_OPTION('m', OPT_MULTIPLE),
00056 AST_APP_OPTION('r', OPT_REMOVE),
00057 });
00058
00059
00060 static const char app[] = "Authenticate";
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 static int auth_exec(struct ast_channel *chan, const char *data)
00113 {
00114 int res = 0, retries, maxdigits;
00115 char passwd[256], *prompt = "agent-pass", *argcopy = NULL;
00116 struct ast_flags flags = {0};
00117
00118 AST_DECLARE_APP_ARGS(arglist,
00119 AST_APP_ARG(password);
00120 AST_APP_ARG(options);
00121 AST_APP_ARG(maxdigits);
00122 AST_APP_ARG(prompt);
00123 );
00124
00125 if (ast_strlen_zero(data)) {
00126 ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
00127 return -1;
00128 }
00129
00130 if (chan->_state != AST_STATE_UP) {
00131 if ((res = ast_answer(chan)))
00132 return -1;
00133 }
00134
00135 argcopy = ast_strdupa(data);
00136
00137 AST_STANDARD_APP_ARGS(arglist, argcopy);
00138
00139 if (!ast_strlen_zero(arglist.options))
00140 ast_app_parse_options(auth_app_options, &flags, NULL, arglist.options);
00141
00142 if (!ast_strlen_zero(arglist.maxdigits)) {
00143 maxdigits = atoi(arglist.maxdigits);
00144 if ((maxdigits<1) || (maxdigits>sizeof(passwd)-2))
00145 maxdigits = sizeof(passwd) - 2;
00146 } else {
00147 maxdigits = sizeof(passwd) - 2;
00148 }
00149
00150 if (!ast_strlen_zero(arglist.prompt)) {
00151 prompt = arglist.prompt;
00152 } else {
00153 prompt = "agent-pass";
00154 }
00155
00156
00157 for (retries = 0; retries < 3; retries++) {
00158 if ((res = ast_app_getdata(chan, prompt, passwd, maxdigits, 0)) < 0)
00159 break;
00160
00161 res = 0;
00162
00163 if (arglist.password[0] != '/') {
00164
00165 if (!strcmp(passwd, arglist.password))
00166 break;
00167 } else if (ast_test_flag(&flags,OPT_DATABASE)) {
00168 char tmp[256];
00169
00170 if (!ast_db_get(arglist.password + 1, passwd, tmp, sizeof(tmp))) {
00171
00172 if (ast_test_flag(&flags,OPT_REMOVE))
00173 ast_db_del(arglist.password + 1, passwd);
00174 break;
00175 }
00176 } else {
00177
00178 FILE *f;
00179 char buf[256] = "", md5passwd[33] = "", *md5secret = NULL;
00180
00181 if (!(f = fopen(arglist.password, "r"))) {
00182 ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", arglist.password, strerror(errno));
00183 continue;
00184 }
00185
00186 for (;;) {
00187 size_t len;
00188
00189 if (feof(f))
00190 break;
00191
00192 if (!fgets(buf, sizeof(buf), f)) {
00193 continue;
00194 }
00195
00196 if (ast_strlen_zero(buf))
00197 continue;
00198
00199 len = strlen(buf) - 1;
00200 if (buf[len] == '\n')
00201 buf[len] = '\0';
00202
00203 if (ast_test_flag(&flags, OPT_MULTIPLE)) {
00204 md5secret = buf;
00205 strsep(&md5secret, ":");
00206 if (!md5secret)
00207 continue;
00208 ast_md5_hash(md5passwd, passwd);
00209 if (!strcmp(md5passwd, md5secret)) {
00210 if (ast_test_flag(&flags,OPT_ACCOUNT))
00211 ast_cdr_setaccount(chan, buf);
00212 break;
00213 }
00214 } else {
00215 if (!strcmp(passwd, buf)) {
00216 if (ast_test_flag(&flags, OPT_ACCOUNT))
00217 ast_cdr_setaccount(chan, buf);
00218 break;
00219 }
00220 }
00221 }
00222
00223 fclose(f);
00224
00225 if (!ast_strlen_zero(buf)) {
00226 if (ast_test_flag(&flags, OPT_MULTIPLE)) {
00227 if (md5secret && !strcmp(md5passwd, md5secret))
00228 break;
00229 } else {
00230 if (!strcmp(passwd, buf))
00231 break;
00232 }
00233 }
00234 }
00235 prompt = "auth-incorrect";
00236 }
00237
00238 if ((retries < 3) && !res) {
00239 if (ast_test_flag(&flags,OPT_ACCOUNT) && !ast_test_flag(&flags,OPT_MULTIPLE))
00240 ast_cdr_setaccount(chan, passwd);
00241 if (!(res = ast_streamfile(chan, "auth-thankyou", chan->language)))
00242 res = ast_waitstream(chan, "");
00243 } else {
00244 if (!ast_streamfile(chan, "vm-goodbye", chan->language))
00245 res = ast_waitstream(chan, "");
00246 res = -1;
00247 }
00248
00249 return res;
00250 }
00251
00252 static int unload_module(void)
00253 {
00254 return ast_unregister_application(app);
00255 }
00256
00257 static int load_module(void)
00258 {
00259 if (ast_register_application_xml(app, auth_exec))
00260 return AST_MODULE_LOAD_FAILURE;
00261 return AST_MODULE_LOAD_SUCCESS;
00262 }
00263
00264 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Authentication Application");