Asterisk - The Open Source Telephony Project  21.4.1
res/ari/cli.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * David M. Lee, II <dlee@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Command line for ARI.
22  * \author David M. Lee, II <dlee@digium.com>
23  */
24 
25 #include "asterisk.h"
26 
27 #include "asterisk/astobj2.h"
28 #include "asterisk/cli.h"
29 #include "asterisk/stasis_app.h"
30 #include "internal.h"
31 
32 static char *ari_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
33 {
34  RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
35 
36  switch (cmd) {
37  case CLI_INIT:
38  e->command = "ari show status";
39  e->usage =
40  "Usage: ari show status\n"
41  " Shows all ARI settings\n";
42  return NULL;
43  case CLI_GENERATE:
44  return NULL;
45  default:
46  break;
47  }
48 
49  if (a->argc != 3) {
50  return CLI_SHOWUSAGE;
51  }
52 
54 
55  if (!conf) {
56  ast_cli(a->fd, "Error getting ARI configuration\n");
57  return CLI_FAILURE;
58  }
59 
60  ast_cli(a->fd, "ARI Status:\n");
61  ast_cli(a->fd, "Enabled: %s\n", AST_CLI_YESNO(conf->general->enabled));
62  ast_cli(a->fd, "Output format: ");
63  if (conf->general->format & AST_JSON_PRETTY) {
64  ast_cli(a->fd, "pretty");
65  } else {
66  ast_cli(a->fd, "compact");
67  }
68  ast_cli(a->fd, "\n");
69  ast_cli(a->fd, "Auth realm: %s\n", conf->general->auth_realm);
70  ast_cli(a->fd, "Allowed Origins: %s\n", conf->general->allowed_origins);
71  ast_cli(a->fd, "User count: %d\n", ao2_container_count(conf->users));
72  return CLI_SUCCESS;
73 }
74 
75 static int show_users_cb(void *obj, void *arg, int flags)
76 {
77  struct ast_ari_conf_user *user = obj;
78  struct ast_cli_args *a = arg;
79 
80  ast_cli(a->fd, "%-4s %s\n",
81  AST_CLI_YESNO(user->read_only),
82  user->username);
83  return 0;
84 }
85 
86 static char *ari_show_users(struct ast_cli_entry *e, int cmd,
87  struct ast_cli_args *a)
88 {
89  RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
90 
91  switch (cmd) {
92  case CLI_INIT:
93  e->command = "ari show users";
94  e->usage =
95  "Usage: ari show users\n"
96  " Shows all ARI users\n";
97  return NULL;
98  case CLI_GENERATE:
99  return NULL;
100  default:
101  break;
102  }
103 
104  if (a->argc != 3) {
105  return CLI_SHOWUSAGE;
106  }
107 
109  if (!conf) {
110  ast_cli(a->fd, "Error getting ARI configuration\n");
111  return CLI_FAILURE;
112  }
113 
114  ast_cli(a->fd, "r/o? Username\n");
115  ast_cli(a->fd, "---- --------\n");
116 
117  ao2_callback(conf->users, OBJ_NODATA, show_users_cb, a);
118 
119  return CLI_SUCCESS;
120 }
121 
123  /*! Nth user to search for */
124  int state;
125  /*! Which user currently on */
126  int which;
127 };
128 
129 static int complete_ari_user_search(void *obj, void *arg, void *data, int flags)
130 {
131  struct user_complete *search = data;
132 
133  if (++search->which > search->state) {
134  return CMP_MATCH;
135  }
136  return 0;
137 }
138 
139 static char *complete_ari_user(struct ast_cli_args *a)
140 {
141  RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
142  RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
143 
144  struct user_complete search = {
145  .state = a->n,
146  };
147 
149  if (!conf) {
150  ast_cli(a->fd, "Error getting ARI configuration\n");
151  return CLI_FAILURE;
152  }
153 
154  user = ao2_callback_data(conf->users,
155  ast_strlen_zero(a->word) ? 0 : OBJ_PARTIAL_KEY,
156  complete_ari_user_search, (char*)a->word, &search);
157 
158  return user ? ast_strdup(user->username) : NULL;
159 }
160 
161 static char *complete_ari_show_user(struct ast_cli_args *a)
162 {
163  if (a->pos == 3) {
164  return complete_ari_user(a);
165  }
166 
167  return NULL;
168 }
169 
170 static char *ari_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
171 {
172  RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
173  RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
174 
175  switch (cmd) {
176  case CLI_INIT:
177  e->command = "ari show user";
178  e->usage =
179  "Usage: ari show user <username>\n"
180  " Shows a specific ARI user\n";
181  return NULL;
182  case CLI_GENERATE:
183  return complete_ari_show_user(a);
184  default:
185  break;
186  }
187 
188  if (a->argc != 4) {
189  return CLI_SHOWUSAGE;
190  }
191 
193 
194  if (!conf) {
195  ast_cli(a->fd, "Error getting ARI configuration\n");
196  return CLI_FAILURE;
197  }
198 
199  user = ao2_find(conf->users, a->argv[3], OBJ_KEY);
200  if (!user) {
201  ast_cli(a->fd, "User '%s' not found\n", a->argv[3]);
202  return CLI_SUCCESS;
203  }
204 
205  ast_cli(a->fd, "Username: %s\n", user->username);
206  ast_cli(a->fd, "Read only?: %s\n", AST_CLI_YESNO(user->read_only));
207 
208  return CLI_SUCCESS;
209 }
210 
211 static char *ari_mkpasswd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
212 {
213  RAII_VAR(char *, crypted, NULL, ast_free);
214 
215  switch (cmd) {
216  case CLI_INIT:
217  e->command = "ari mkpasswd";
218  e->usage =
219  "Usage: ari mkpasswd <password>\n"
220  " Encrypts a password for use in ari.conf\n"
221  " Be aware that the password will be shown in the\n"
222  " command line history. The mkpasswd shell command\n"
223  " may be preferable.\n"
224  ;
225  return NULL;
226  case CLI_GENERATE:
227  return NULL;
228  default:
229  break;
230  }
231 
232  if (a->argc != 3) {
233  return CLI_SHOWUSAGE;
234  }
235 
236  crypted = ast_crypt_encrypt(a->argv[2]);
237  if (!crypted) {
238  ast_cli(a->fd, "Failed to encrypt password\n");
239  return CLI_FAILURE;
240  }
241 
242  ast_cli(a->fd,
243  "; Copy the following two lines into ari.conf\n");
244  ast_cli(a->fd, "password_format = crypt\n");
245  ast_cli(a->fd, "password = %s\n", crypted);
246 
247  return CLI_SUCCESS;
248 }
249 
250 static char *ari_show_apps(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
251 {
252  struct ao2_container *apps;
253  struct ao2_iterator it_apps;
254  char *app;
255 
256  switch (cmd) {
257  case CLI_INIT:
258  e->command = "ari show apps";
259  e->usage =
260  "Usage: ari show apps\n"
261  " Lists all registered applications.\n"
262  ;
263  return NULL;
264  case CLI_GENERATE:
265  return NULL;
266  default:
267  break;
268  }
269 
270  if (a->argc != 3) {
271  return CLI_SHOWUSAGE;
272  }
273 
274  apps = stasis_app_get_all();
275  if (!apps) {
276  ast_cli(a->fd, "Unable to retrieve registered applications!\n");
277  return CLI_FAILURE;
278  }
279 
280  ast_cli(a->fd, "Application Name \n");
281  ast_cli(a->fd, "=========================\n");
282  it_apps = ao2_iterator_init(apps, 0);
283  while ((app = ao2_iterator_next(&it_apps))) {
284  ast_cli(a->fd, "%-25.25s\n", app);
285  ao2_ref(app, -1);
286  }
287 
288  ao2_iterator_destroy(&it_apps);
289  ao2_ref(apps, -1);
290 
291  return CLI_SUCCESS;
292 }
293 
294 struct app_complete {
295  /*! Nth app to search for */
296  int state;
297  /*! Which app currently on */
298  int which;
299 };
300 
301 static int complete_ari_app_search(void *obj, void *arg, void *data, int flags)
302 {
303  struct app_complete *search = data;
304 
305  if (++search->which > search->state) {
306  return CMP_MATCH;
307  }
308  return 0;
309 }
310 
311 static char *complete_ari_app(struct ast_cli_args *a, int include_all)
312 {
313  RAII_VAR(struct ao2_container *, apps, stasis_app_get_all(), ao2_cleanup);
314  RAII_VAR(char *, app, NULL, ao2_cleanup);
315 
316  struct app_complete search = {
317  .state = a->n,
318  };
319 
320  if (a->pos != 3) {
321  return NULL;
322  }
323 
324  if (!apps) {
325  ast_cli(a->fd, "Error getting ARI applications\n");
326  return CLI_FAILURE;
327  }
328 
329  if (include_all && ast_strlen_zero(a->word)) {
330  ast_str_container_add(apps, " all");
331  }
332 
333  app = ao2_callback_data(apps,
334  ast_strlen_zero(a->word) ? 0 : OBJ_SEARCH_PARTIAL_KEY,
335  complete_ari_app_search, (char*)a->word, &search);
336 
337  return app ? ast_strdup(app) : NULL;
338 }
339 
340 static char *ari_show_app(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
341 {
342  void *app;
343 
344  switch (cmd) {
345  case CLI_INIT:
346  e->command = "ari show app";
347  e->usage =
348  "Usage: ari show app <application>\n"
349  " Provide detailed information about a registered application.\n"
350  ;
351  return NULL;
352  case CLI_GENERATE:
353  return complete_ari_app(a, 0);
354  default:
355  break;
356  }
357 
358  if (a->argc != 4) {
359  return CLI_SHOWUSAGE;
360  }
361 
362  app = stasis_app_get_by_name(a->argv[3]);
363  if (!app) {
364  return CLI_FAILURE;
365  }
366 
367  stasis_app_to_cli(app, a);
368 
369  ao2_ref(app, -1);
370 
371  return CLI_SUCCESS;
372 }
373 
374 static char *ari_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
375 {
376  void *app;
377  int debug;
378 
379  switch (cmd) {
380  case CLI_INIT:
381  e->command = "ari set debug";
382  e->usage =
383  "Usage: ari set debug <application|all> <on|off>\n"
384  " Enable or disable debugging on a specific application.\n"
385  ;
386  return NULL;
387  case CLI_GENERATE:
388  return complete_ari_app(a, 1);
389  default:
390  break;
391  }
392 
393  if (a->argc != 5) {
394  return CLI_SHOWUSAGE;
395  }
396 
397  debug = !strcmp(a->argv[4], "on");
398 
399  if (!strcmp(a->argv[3], "all")) {
401  ast_cli(a->fd, "Debugging on all applications %s\n",
402  debug ? "enabled" : "disabled");
403  return CLI_SUCCESS;
404  }
405 
406  app = stasis_app_get_by_name(a->argv[3]);
407  if (!app) {
408  return CLI_FAILURE;
409  }
410 
411  stasis_app_set_debug(app, debug);
412  ast_cli(a->fd, "Debugging on '%s' %s\n",
413  stasis_app_name(app),
414  debug ? "enabled" : "disabled");
415 
416  ao2_ref(app, -1);
417 
418  return CLI_SUCCESS;
419 }
420 
421 static struct ast_cli_entry cli_ari[] = {
422  AST_CLI_DEFINE(ari_show, "Show ARI settings"),
423  AST_CLI_DEFINE(ari_show_users, "List ARI users"),
424  AST_CLI_DEFINE(ari_show_user, "List single ARI user"),
425  AST_CLI_DEFINE(ari_mkpasswd, "Encrypts a password"),
426  AST_CLI_DEFINE(ari_show_apps, "List registered ARI applications"),
427  AST_CLI_DEFINE(ari_show_app, "Display details of a registered ARI application"),
428  AST_CLI_DEFINE(ari_set_debug, "Enable/disable debugging of an ARI application"),
429 };
430 
432  return ast_cli_register_multiple(cli_ari, ARRAY_LEN(cli_ari));
433 }
434 
436  ast_cli_unregister_multiple(cli_ari, ARRAY_LEN(cli_ari));
437 }
struct stasis_app * stasis_app_get_by_name(const char *name)
Retrieve a handle to a Stasis application by its name.
Definition: res_stasis.c:1701
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
Registered applications container.
Definition: pbx_app.c:67
struct ast_ari_conf * ast_ari_config_get(void)
Get the current ARI configuration.
#define OBJ_KEY
Definition: astobj2.h:1151
descriptor for a cli entry.
Definition: cli.h:171
static int debug
Global debug status.
Definition: res_xmpp.c:441
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1693
All configuration options for ARI.
Definition: internal.h:54
void stasis_app_to_cli(const struct stasis_app *app, struct ast_cli_args *a)
Dump properties of a stasis_app to the CLI.
char * username
Definition: internal.h:98
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1152
All configuration options for http media cache.
struct conf_general_options * general
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application's name.
int ast_ari_cli_register(void)
Register CLI commands for ARI.
Definition: res/ari/cli.c:431
Per-user configuration options.
Definition: internal.h:96
Internal API's for res_ari.
void stasis_app_set_global_debug(int debug)
Enable/disable request/response and event logging on all applications.
char * command
Definition: cli.h:186
struct ao2_container * stasis_app_get_all(void)
Gets the names of all registered Stasis applications.
Definition: res_stasis.c:1715
structure to hold users read from users.conf
const char * usage
Definition: cli.h:177
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Standard Command Line Interface.
void ast_ari_cli_unregister(void)
Unregister CLI commands for ARI.
Definition: res/ari/cli.c:435
void stasis_app_set_debug(struct stasis_app *app, int debug)
Enable/disable request/response and event logging on an application.
Stasis Application API. See Stasis Application API for detailed documentation.
Generic container type.
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition: cli.h:71
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
Definition: strings.c:205
char * ast_crypt_encrypt(const char *key)
Asterisk wrapper around crypt(3) for encrypting passwords.
Definition: crypt.c:190