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: 348362 $")
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
00113
00114
00115
00116
00117
00118 static int auth_exec(struct ast_channel *chan, const char *data)
00119 {
00120 int res = 0, retries, maxdigits;
00121 char passwd[256], *prompt = "agent-pass", *argcopy = NULL;
00122 struct ast_flags flags = {0};
00123
00124 AST_DECLARE_APP_ARGS(arglist,
00125 AST_APP_ARG(password);
00126 AST_APP_ARG(options);
00127 AST_APP_ARG(maxdigits);
00128 AST_APP_ARG(prompt);
00129 );
00130
00131 if (ast_strlen_zero(data)) {
00132 ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
00133 return -1;
00134 }
00135
00136 if (chan->_state != AST_STATE_UP) {
00137 if ((res = ast_answer(chan)))
00138 return -1;
00139 }
00140
00141 argcopy = ast_strdupa(data);
00142
00143 AST_STANDARD_APP_ARGS(arglist, argcopy);
00144
00145 if (!ast_strlen_zero(arglist.options))
00146 ast_app_parse_options(auth_app_options, &flags, NULL, arglist.options);
00147
00148 if (!ast_strlen_zero(arglist.maxdigits)) {
00149 maxdigits = atoi(arglist.maxdigits);
00150 if ((maxdigits<1) || (maxdigits>sizeof(passwd)-2))
00151 maxdigits = sizeof(passwd) - 2;
00152 } else {
00153 maxdigits = sizeof(passwd) - 2;
00154 }
00155
00156 if (!ast_strlen_zero(arglist.prompt)) {
00157 prompt = arglist.prompt;
00158 } else {
00159 prompt = "agent-pass";
00160 }
00161
00162
00163 for (retries = 0; retries < 3; retries++) {
00164 if ((res = ast_app_getdata(chan, prompt, passwd, maxdigits, 0)) < 0)
00165 break;
00166
00167 res = 0;
00168
00169 if (arglist.password[0] != '/') {
00170
00171 if (!strcmp(passwd, arglist.password))
00172 break;
00173 } else if (ast_test_flag(&flags,OPT_DATABASE)) {
00174 char tmp[256];
00175
00176 if (!ast_db_get(arglist.password + 1, passwd, tmp, sizeof(tmp))) {
00177
00178 if (ast_test_flag(&flags,OPT_REMOVE))
00179 ast_db_del(arglist.password + 1, passwd);
00180 break;
00181 }
00182 } else {
00183
00184 FILE *f;
00185 char buf[256] = "", md5passwd[33] = "", *md5secret = NULL;
00186
00187 if (!(f = fopen(arglist.password, "r"))) {
00188 ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", arglist.password, strerror(errno));
00189 continue;
00190 }
00191
00192 for (;;) {
00193 size_t len;
00194
00195 if (feof(f))
00196 break;
00197
00198 if (!fgets(buf, sizeof(buf), f)) {
00199 continue;
00200 }
00201
00202 if (ast_strlen_zero(buf))
00203 continue;
00204
00205 len = strlen(buf) - 1;
00206 if (buf[len] == '\n')
00207 buf[len] = '\0';
00208
00209 if (ast_test_flag(&flags, OPT_MULTIPLE)) {
00210 md5secret = buf;
00211 strsep(&md5secret, ":");
00212 if (!md5secret)
00213 continue;
00214 ast_md5_hash(md5passwd, passwd);
00215 if (!strcmp(md5passwd, md5secret)) {
00216 if (ast_test_flag(&flags,OPT_ACCOUNT)) {
00217 ast_channel_lock(chan);
00218 ast_cdr_setaccount(chan, buf);
00219 ast_channel_unlock(chan);
00220 }
00221 break;
00222 }
00223 } else {
00224 if (!strcmp(passwd, buf)) {
00225 if (ast_test_flag(&flags, OPT_ACCOUNT)) {
00226 ast_channel_lock(chan);
00227 ast_cdr_setaccount(chan, buf);
00228 ast_channel_unlock(chan);
00229 }
00230 break;
00231 }
00232 }
00233 }
00234
00235 fclose(f);
00236
00237 if (!ast_strlen_zero(buf)) {
00238 if (ast_test_flag(&flags, OPT_MULTIPLE)) {
00239 if (md5secret && !strcmp(md5passwd, md5secret))
00240 break;
00241 } else {
00242 if (!strcmp(passwd, buf))
00243 break;
00244 }
00245 }
00246 }
00247 prompt = "auth-incorrect";
00248 }
00249
00250 if ((retries < 3) && !res) {
00251 if (ast_test_flag(&flags,OPT_ACCOUNT) && !ast_test_flag(&flags,OPT_MULTIPLE)) {
00252 ast_channel_lock(chan);
00253 ast_cdr_setaccount(chan, passwd);
00254 ast_channel_unlock(chan);
00255 }
00256 if (!(res = ast_streamfile(chan, "auth-thankyou", chan->language)))
00257 res = ast_waitstream(chan, "");
00258 } else {
00259 if (!ast_streamfile(chan, "vm-goodbye", chan->language))
00260 res = ast_waitstream(chan, "");
00261 res = -1;
00262 }
00263
00264 return res;
00265 }
00266
00267 static int unload_module(void)
00268 {
00269 return ast_unregister_application(app);
00270 }
00271
00272 static int load_module(void)
00273 {
00274 if (ast_register_application_xml(app, auth_exec))
00275 return AST_MODULE_LOAD_FAILURE;
00276 return AST_MODULE_LOAD_SUCCESS;
00277 }
00278
00279 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Authentication Application");