~ubuntu-branches/ubuntu/karmic/asterisk/karmic-security

1.1.2 by Kilian Krause
Import upstream version 1.0.6
1
/*
1.1.4 by Mark Purcell
Import upstream version 1.2.1.dfsg
2
 * Asterisk -- An open source telephony toolkit.
3
 *
4
 * Copyright (c) 2004 - 2005, Tilghman Lesher.  All rights reserved.
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
5
 * Portions copyright (c) 2006, Philipp Dunkel.
1.1.2 by Kilian Krause
Import upstream version 1.0.6
6
 *
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
7
 * Tilghman Lesher <app_exec__v002@the-tilghman.com>
1.1.2 by Kilian Krause
Import upstream version 1.0.6
8
 *
9
 * This code is released by the author with no restrictions on usage.
10
 *
1.1.4 by Mark Purcell
Import upstream version 1.2.1.dfsg
11
 * See http://www.asterisk.org for more information about
12
 * the Asterisk project. Please do not directly contact
13
 * any of the maintainers of this project for assistance;
14
 * the project provides a web site, mailing lists and IRC
15
 * channels for your use.
16
 *
17
 */
18
19
/*! \file
20
 *
21
 * \brief Exec application
22
 *
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
23
 * \author Tilghman Lesher <app_exec__v002@the-tilghman.com>
24
 * \author Philipp Dunkel <philipp.dunkel@ebox.at>
1.1.4 by Mark Purcell
Import upstream version 1.2.1.dfsg
25
 *
26
 * \ingroup applications
1.1.2 by Kilian Krause
Import upstream version 1.0.6
27
 */
28
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
29
#include "asterisk.h"
30
1.2.2 by Faidon Liambotis
Import upstream version 1.6.2.0~dfsg~beta3
31
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 153468 $")
1.1.4 by Mark Purcell
Import upstream version 1.2.1.dfsg
32
33
#include "asterisk/file.h"
34
#include "asterisk/channel.h"
35
#include "asterisk/pbx.h"
36
#include "asterisk/module.h"
1.1.23 by Mark Purcell
Import upstream version 1.6.1.0~dfsg~rc3
37
#include "asterisk/app.h"
1.1.2 by Kilian Krause
Import upstream version 1.0.6
38
1.2.2 by Faidon Liambotis
Import upstream version 1.6.2.0~dfsg~beta3
39
/*** DOCUMENTATION
40
	<application name="Exec" language="en_US">
41
		<synopsis>
42
			Executes dialplan application.
43
		</synopsis>
44
		<syntax>
45
			<parameter name="appname" required="true" hasparams="true">
46
				<para>Application name and arguments of the dialplan application to execute.</para>
47
				<argument name="arguments" required="true" />
48
			</parameter>
49
		</syntax>
50
		<description>
51
			<para>Allows an arbitrary application to be invoked even when not
52
			hard coded into the dialplan.  If the underlying application
53
			terminates the dialplan, or if the application cannot be found,
54
			Exec will terminate the dialplan.</para>
55
			<para>To invoke external applications, see the application System.
56
			If you would like to catch any error instead, see TryExec.</para>
57
		</description>
58
	</application>
59
	<application name="TryExec" language="en_US">
60
		<synopsis>
61
			Executes dialplan application, always returning.
62
		</synopsis>
63
		<syntax>
64
			<parameter name="appname" required="true" hasparams="true">
65
				<argument name="arguments" required="true" />
66
			</parameter>
67
		</syntax>
68
		<description>
69
			<para>Allows an arbitrary application to be invoked even when not
70
			hard coded into the dialplan. To invoke external applications
71
			see the application System.  Always returns to the dialplan.
72
			The channel variable TRYSTATUS will be set to one of:
73
			</para>
74
			<variablelist>
75
				<variable name="TRYSTATUS">
76
					<value name="SUCCESS">
77
						If the application returned zero.
78
					</value>
79
					<value name="FAILED">
80
						If the application returned non-zero.
81
					</value>
82
					<value name="NOAPP">
83
						If the application was not found or was not specified.
84
					</value>
85
				</variable>
86
			</variablelist>
87
		</description>
88
	</application>
89
	<application name="ExecIf" language="en_US">
90
		<synopsis>
91
			Executes dialplan application, conditionally.
92
		</synopsis>
93
		<syntax argsep="?">
94
			<parameter name="expression" required="true" />
95
			<parameter name="execapp" required="true" argsep=":">
96
				<argument name="appiftrue" required="true" hasparams="true">
97
					<argument name="args" required="true" />
98
				</argument>
99
				<argument name="appiffalse" required="false" hasparams="true">
100
					<argument name="args" required="true" />
101
				</argument>
102
			</parameter>
103
		</syntax>
104
		<description>
105
			<para>If <replaceable>expr</replaceable> is true, execute and return the
106
			result of <replaceable>appiftrue(args)</replaceable>.</para>
107
			<para>If <replaceable>expr</replaceable> is true, but <replaceable>appiftrue</replaceable> is not found,
108
			then the application will return a non-zero value.</para>
109
		</description>
110
	</application>
111
 ***/
112
1.1.2 by Kilian Krause
Import upstream version 1.0.6
113
/* Maximum length of any variable */
1.1.23 by Mark Purcell
Import upstream version 1.6.1.0~dfsg~rc3
114
#define MAXRESULT 1024
1.1.2 by Kilian Krause
Import upstream version 1.0.6
115
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
116
/*! Note
117
 *
118
 * The key difference between these two apps is exit status.  In a
119
 * nutshell, Exec tries to be transparent as possible, behaving
120
 * in exactly the same way as if the application it calls was
121
 * directly invoked from the dialplan.
122
 *
123
 * TryExec, on the other hand, provides a way to execute applications
124
 * and catch any possible fatal error without actually fatally
125
 * affecting the dialplan.
126
 */
1.1.2 by Kilian Krause
Import upstream version 1.0.6
127
128
static char *app_exec = "Exec";
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
129
static char *app_tryexec = "TryExec";
130
static char *app_execif = "ExecIf";
1.1.2 by Kilian Krause
Import upstream version 1.0.6
131
132
static int exec_exec(struct ast_channel *chan, void *data)
133
{
1.1.23 by Mark Purcell
Import upstream version 1.6.1.0~dfsg~rc3
134
	int res = 0;
135
	char *s, *appname, *endargs, args[MAXRESULT];
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
136
	struct ast_app *app;
137
1.1.23 by Mark Purcell
Import upstream version 1.6.1.0~dfsg~rc3
138
	if (ast_strlen_zero(data))
139
		return 0;
140
141
	s = ast_strdupa(data);
142
	args[0] = 0;
143
	appname = strsep(&s, "(");
144
	if (s) {
145
		endargs = strrchr(s, ')');
146
		if (endargs)
147
			*endargs = '\0';
148
		pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
149
	}
150
	if (appname) {
151
		app = pbx_findapp(appname);
152
		if (app) {
153
			res = pbx_exec(chan, app, args);
154
		} else {
155
			ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
156
			res = -1;
157
		}
158
	}
159
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
160
	return res;
161
}
162
163
static int tryexec_exec(struct ast_channel *chan, void *data)
164
{
1.1.23 by Mark Purcell
Import upstream version 1.6.1.0~dfsg~rc3
165
	int res = 0;
166
	char *s, *appname, *endargs, args[MAXRESULT];
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
167
	struct ast_app *app;
168
1.1.23 by Mark Purcell
Import upstream version 1.6.1.0~dfsg~rc3
169
	if (ast_strlen_zero(data))
170
		return 0;
171
172
	s = ast_strdupa(data);
173
	args[0] = 0;
174
	appname = strsep(&s, "(");
175
	if (s) {
176
		endargs = strrchr(s, ')');
177
		if (endargs)
178
			*endargs = '\0';
179
		pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
180
	}
181
	if (appname) {
182
		app = pbx_findapp(appname);
183
		if (app) {
184
			res = pbx_exec(chan, app, args);
185
			pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
186
		} else {
187
			ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
188
			pbx_builtin_setvar_helper(chan, "TRYSTATUS", "NOAPP");
189
		}
190
	}
191
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
192
	return 0;
193
}
194
195
static int execif_exec(struct ast_channel *chan, void *data)
196
{
197
	int res = 0;
1.1.23 by Mark Purcell
Import upstream version 1.6.1.0~dfsg~rc3
198
	char *truedata = NULL, *falsedata = NULL, *end, *firstcomma, *firstquestion;
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
199
	struct ast_app *app = NULL;
1.1.23 by Mark Purcell
Import upstream version 1.6.1.0~dfsg~rc3
200
	AST_DECLARE_APP_ARGS(expr,
201
		AST_APP_ARG(expr);
202
		AST_APP_ARG(remainder);
203
	);
204
	AST_DECLARE_APP_ARGS(apps,
205
		AST_APP_ARG(t);
206
		AST_APP_ARG(f);
207
	);
208
	char *parse = ast_strdupa(data);
209
210
	firstcomma = strchr(parse, ',');
211
	firstquestion = strchr(parse, '?');
212
213
	if ((firstcomma != NULL && firstquestion != NULL && firstcomma < firstquestion) || (firstquestion == NULL)) {
214
		/* Deprecated syntax */
215
		AST_DECLARE_APP_ARGS(depr,
216
			AST_APP_ARG(expr);
217
			AST_APP_ARG(appname);
218
			AST_APP_ARG(appargs);
219
		);
220
		AST_STANDARD_APP_ARGS(depr, parse);
221
222
		ast_log(LOG_WARNING, "Deprecated syntax found.  Please upgrade to using ExecIf(<expr>?%s(%s))\n", depr.appname, depr.appargs);
223
224
		/* Make the two syntaxes look the same */
225
		expr.expr = depr.expr;
226
		apps.t = depr.appname;
227
		apps.f = NULL;
228
		truedata = depr.appargs;
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
229
	} else {
1.1.23 by Mark Purcell
Import upstream version 1.6.1.0~dfsg~rc3
230
		/* Preferred syntax */
231
232
		AST_NONSTANDARD_APP_ARGS(expr, parse, '?');
233
		if (ast_strlen_zero(expr.remainder)) {
234
			ast_log(LOG_ERROR, "Usage: ExecIf(<expr>?<appiftrue>(<args>)[:<appiffalse>(<args)])\n");
235
			return -1;
236
		}
237
238
		AST_NONSTANDARD_APP_ARGS(apps, expr.remainder, ':');
239
240
		if (apps.t && (truedata = strchr(apps.t, '('))) {
241
			*truedata++ = '\0';
242
			if ((end = strrchr(truedata, ')'))) {
243
				*end = '\0';
244
			}
245
		}
246
247
		if (apps.f && (falsedata = strchr(apps.f, '('))) {
248
			*falsedata++ = '\0';
249
			if ((end = strrchr(falsedata, ')'))) {
250
				*end = '\0';
251
			}
252
		}
253
	}
254
255
	if (pbx_checkcondition(expr.expr)) {
256
		if (!ast_strlen_zero(apps.t) && (app = pbx_findapp(apps.t))) {
257
			res = pbx_exec(chan, app, S_OR(truedata, ""));
258
		} else {
259
			ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.t);
260
			res = -1;
261
		}
262
	} else if (!ast_strlen_zero(apps.f)) {
263
		if ((app = pbx_findapp(apps.f))) {
264
			res = pbx_exec(chan, app, S_OR(falsedata, ""));
265
		} else {
266
			ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.f);
267
			res = -1;
268
		}
269
	}
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
270
271
	return res;
272
}
273
274
static int unload_module(void)
1.1.2 by Kilian Krause
Import upstream version 1.0.6
275
{
1.1.4 by Mark Purcell
Import upstream version 1.2.1.dfsg
276
	int res;
277
278
	res = ast_unregister_application(app_exec);
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
279
	res |= ast_unregister_application(app_tryexec);
280
	res |= ast_unregister_application(app_execif);
281
282
	return res;
283
}
284
285
static int load_module(void)
286
{
1.2.2 by Faidon Liambotis
Import upstream version 1.6.2.0~dfsg~beta3
287
	int res = ast_register_application_xml(app_exec, exec_exec);
288
	res |= ast_register_application_xml(app_tryexec, tryexec_exec);
289
	res |= ast_register_application_xml(app_execif, execif_exec);
1.1.11 by Lionel Porcheron
Import upstream version 1.4.4~dfsg
290
	return res;
291
}
292
293
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Executes dialplan applications");