Wed Oct 28 15:47:47 2009

Asterisk developer's documentation


app_authenticate.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  * \brief Execute arbitrary authenticate commands
00021  * 
00022  * \ingroup applications
00023  */
00024 
00025 #include <stdlib.h>
00026 #include <unistd.h>
00027 #include <string.h>
00028 #include <errno.h>
00029 #include <stdio.h>
00030 
00031 #include "asterisk.h"
00032 
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 42421 $")
00034 
00035 #include "asterisk/lock.h"
00036 #include "asterisk/file.h"
00037 #include "asterisk/logger.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 static char *tdesc = "Authentication Application";
00046 
00047 static char *app = "Authenticate";
00048 
00049 static char *synopsis = "Authenticate a user";
00050 
00051 static char *descrip =
00052 "  Authenticate(password[|options]): This application asks the caller to enter a\n"
00053 "given password in order to continue dialplan execution. If the password begins\n"
00054 "with the '/' character, it is interpreted as a file which contains a list of\n"
00055 "valid passwords, listed 1 password per line in the file.\n"
00056 "  When using a database key, the value associated with the key can be anything.\n"
00057 "Users have three attempts to authenticate before the channel is hung up. If the\n"
00058 "passsword is invalid, the 'j' option is specified, and priority n+101 exists,\n"
00059 "dialplan execution will continnue at this location.\n"
00060 "  Options:\n"
00061 "     a - Set the channels' account code to the password that is entered\n"
00062 "     d - Interpret the given path as database key, not a literal file\n"
00063 "     j - Support jumping to n+101 if authentication fails\n"
00064 "     m - Interpret the given path as a file which contains a list of account\n"
00065 "         codes and password hashes delimited with ':', listed one per line in\n"
00066 "         the file. When one of the passwords is matched, the channel will have\n"
00067 "         its account code set to the corresponding account code in the file.\n"
00068 "     r - Remove the database key upon successful entry (valid with 'd' only)\n"
00069 ;
00070 
00071 STANDARD_LOCAL_USER;
00072 
00073 LOCAL_USER_DECL;
00074 
00075 static int auth_exec(struct ast_channel *chan, void *data)
00076 {
00077    int res=0;
00078    int jump = 0;
00079    int retries;
00080    struct localuser *u;
00081    char password[256]="";
00082    char passwd[256];
00083    char *opts;
00084    char *prompt;
00085    
00086    if (ast_strlen_zero(data)) {
00087       ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
00088       return -1;
00089    }
00090    
00091    LOCAL_USER_ADD(u);
00092 
00093    if (chan->_state != AST_STATE_UP) {
00094       res = ast_answer(chan);
00095       if (res) {
00096          LOCAL_USER_REMOVE(u);
00097          return -1;
00098       }
00099    }
00100    
00101    strncpy(password, data, sizeof(password) - 1);
00102    opts=strchr(password, '|');
00103    if (opts) {
00104       *opts = 0;
00105       opts++;
00106    } else
00107       opts = "";
00108    if (strchr(opts, 'j'))
00109       jump = 1;
00110    /* Start asking for password */
00111    prompt = "agent-pass";
00112    for (retries = 0; retries < 3; retries++) {
00113       res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0);
00114       if (res < 0)
00115          break;
00116       res = 0;
00117       if (password[0] == '/') {
00118          if (strchr(opts, 'd')) {
00119             char tmp[256];
00120             /* Compare against a database key */
00121             if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) {
00122                /* It's a good password */
00123                if (strchr(opts, 'r')) {
00124                   ast_db_del(password + 1, passwd);
00125                }
00126                break;
00127             }
00128          } else {
00129             /* Compare against a file */
00130             FILE *f;
00131             f = fopen(password, "r");
00132             if (f) {
00133                char buf[256] = "";
00134                char md5passwd[33] = "";
00135                char *md5secret = NULL;
00136 
00137                while (!feof(f)) {
00138                   fgets(buf, sizeof(buf), f);
00139                   if (!feof(f) && !ast_strlen_zero(buf)) {
00140                      buf[strlen(buf) - 1] = '\0';
00141                      if (strchr(opts, 'm')) {
00142                         md5secret = strchr(buf, ':');
00143                         if (md5secret == NULL)
00144                            continue;
00145                         *md5secret = '\0';
00146                         md5secret++;
00147                         ast_md5_hash(md5passwd, passwd);
00148                         if (!strcmp(md5passwd, md5secret)) {
00149                            if (strchr(opts, 'a'))
00150                               ast_cdr_setaccount(chan, buf);
00151                            break;
00152                         }
00153                      } else {
00154                         if (!strcmp(passwd, buf)) {
00155                            if (strchr(opts, 'a'))
00156                               ast_cdr_setaccount(chan, buf);
00157                            break;
00158                         }
00159                      }
00160                   }
00161                }
00162                fclose(f);
00163                if (!ast_strlen_zero(buf)) {
00164                   if (strchr(opts, 'm')) {
00165                      if (md5secret && !strcmp(md5passwd, md5secret))
00166                         break;
00167                   } else {
00168                      if (!strcmp(passwd, buf))
00169                         break;
00170                   }
00171                }
00172             } else 
00173                ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
00174          }
00175       } else {
00176          /* Compare against a fixed password */
00177          if (!strcmp(passwd, password)) 
00178             break;
00179       }
00180       prompt="auth-incorrect";
00181    }
00182    if ((retries < 3) && !res) {
00183       if (strchr(opts, 'a') && !strchr(opts, 'm')) 
00184          ast_cdr_setaccount(chan, passwd);
00185       res = ast_streamfile(chan, "auth-thankyou", chan->language);
00186       if (!res)
00187          res = ast_waitstream(chan, "");
00188    } else {
00189       if (jump && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0) {
00190          res = 0;
00191       } else {
00192          if (!ast_streamfile(chan, "vm-goodbye", chan->language))
00193             res = ast_waitstream(chan, "");
00194          res = -1;
00195       }
00196    }
00197    LOCAL_USER_REMOVE(u);
00198    return res;
00199 }
00200 
00201 int unload_module(void)
00202 {
00203    int res;
00204 
00205    res = ast_unregister_application(app);
00206 
00207    STANDARD_HANGUP_LOCALUSERS;
00208    
00209    return res;
00210 }
00211 
00212 int load_module(void)
00213 {
00214    return ast_register_application(app, auth_exec, synopsis, descrip);
00215 }
00216 
00217 char *description(void)
00218 {
00219    return tdesc;
00220 }
00221 
00222 int usecount(void)
00223 {
00224    int res;
00225    STANDARD_USECOUNT(res);
00226    return res;
00227 }
00228 
00229 char *key()
00230 {
00231    return ASTERISK_GPL_KEY;
00232 }

Generated on Wed Oct 28 15:47:47 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6