589ef06ba4c9a9fdef7f4f2f1c4dcf73c5d97409
[asterisk/asterisk.git] / apps / app_authenticate.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Execute arbitrary authenticate commands
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/module.h>
20 #include <asterisk/app.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <pthread.h>
28
29
30 static char *tdesc = "Authentication Application";
31
32 static char *app = "Authenticate";
33
34 static char *synopsis = "Authenticate a user";
35
36 static char *descrip =
37 "  Authenticate(password[|options]): Requires a user to enter a"
38 "given password in order to continue execution.  If the\n"
39 "password begins with the '/' character, it is interpreted as\n"
40 "a file which contains a list of valid passwords (1 per line).\n"
41 "an optional set of opions may be provided by concatenating any\n"
42 "of the following letters:\n"
43 "     a - Set account code to the password that is entered\n"
44 "\n"
45 "Returns 0 if the user enters a valid password within three\n"
46 "tries, or -1 otherwise (or on hangup).\n";
47
48 STANDARD_LOCAL_USER;
49
50 LOCAL_USER_DECL;
51
52 static int auth_exec(struct ast_channel *chan, void *data)
53 {
54         int res=0;
55         int retries;
56         struct localuser *u;
57         char password[256]="";
58         char passwd[256];
59         char *opts;
60         char *prompt;
61         if (!data || !strlen(data)) {
62                 ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
63                 return -1;
64         }
65         LOCAL_USER_ADD(u);
66         if (chan->_state != AST_STATE_UP) {
67                 res = ast_answer(chan);
68                 if (res) {
69                         LOCAL_USER_REMOVE(u);
70                         return -1;
71                 }
72         }
73         strncpy(password, data, sizeof(password) - 1);
74         opts=strchr(password, '|');
75         if (opts) {
76                 *opts = 0;
77                 opts++;
78         } else
79                 opts = "";
80         /* Start asking for password */
81         prompt = "agent-pass";
82         for (retries = 0; retries < 3; retries++) {
83                 res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0);
84                 if (res < 0)
85                         break;
86                 res = 0;
87                 if (password[0] == '/') {
88                         /* Compare against a file */
89                         FILE *f;
90                         f = fopen(password, "r");
91                         if (f) {
92                                 char buf[256] = "";
93                                 while(!feof(f)) {
94                                         fgets(buf, sizeof(buf), f);
95                                         if (!feof(f) && strlen(buf)) {
96                                                 buf[strlen(buf) - 1] = '\0';
97                                                 if (strlen(buf) && !strcmp(passwd, buf))
98                                                         break;
99                                         }
100                                 }
101                                 fclose(f);
102                                 if (strlen(buf) && !strcmp(passwd, buf))
103                                         break;
104                         } else 
105                                 ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
106                 } else {
107                         /* Compare against a fixed password */
108                         if (!strcmp(passwd, password)) 
109                                 break;
110                 }
111                 prompt="auth-incorrect";
112         }
113         if ((retries < 3) && !res) {
114                 if (strchr(opts, 'a')) 
115                         ast_cdr_setaccount(chan, passwd);
116                 res = ast_streamfile(chan, "auth-thankyou", chan->language);
117                 if (!res)
118                         res = ast_waitstream(chan, "");
119         } else {
120                 if (!res)
121                         res = ast_streamfile(chan, "vm-goodbye", chan->language);
122                 if (!res)
123                         res = ast_waitstream(chan, "");
124                 res = -1;
125         }
126         LOCAL_USER_REMOVE(u);
127         return res;
128 }
129
130 int unload_module(void)
131 {
132         STANDARD_HANGUP_LOCALUSERS;
133         return ast_unregister_application(app);
134 }
135
136 int load_module(void)
137 {
138         return ast_register_application(app, auth_exec, synopsis, descrip);
139 }
140
141 char *description(void)
142 {
143         return tdesc;
144 }
145
146 int usecount(void)
147 {
148         int res;
149         STANDARD_USECOUNT(res);
150         return res;
151 }
152
153 char *key()
154 {
155         return ASTERISK_GPL_KEY;
156 }