Merged revisions 378410,378412,378414 via svnmerge from

file:///srv/subversion/repos/asterisk/trunk

................
  r378410 | mjordan | 2013-01-03 09:37:31 -0600 (Thu, 03 Jan 2013) | 13 lines
  
  Prevent crashes in res_xmpp when receiving large messages
  
  Similar to r378287, res_xmpp was marshaling data read from an external source
  onto the stack. For a sufficiently large message, this could cause a stack
  overflow. This patch modifies res_xmpp in a similar fashion to res_jabber by
  removing the stack allocation, as it was unnecessary.
  
  (issue ASTERISK-20658)
  Reported by: wdoekes
  ........
  
  Merged revisions 378409 from http://svn.asterisk.org/svn/asterisk/branches/11
................
  r378412 | file | 2013-01-03 09:40:21 -0600 (Thu, 03 Jan 2013) | 11 lines
  
  Prevent exhaustion of system resources through exploitation of event cache
  
  This patch changes res_xmpp to no longer cache events under certain circumstances.
  
  (issue ASTERISK-20175)
  Reported by: Russell Bryant, Leif Madsen, Joshua Colp
  Tested by: kmoore
  ........
  
  Merged revisions 378411 from http://svn.asterisk.org/svn/asterisk/branches/11
................
  r378414 | tilghman | 2013-01-03 10:04:11 -0600 (Thu, 03 Jan 2013) | 11 lines
  
  Add aliases to the Directory.
  
  This is an interesting feature that allows additional strings to be used to
  search the Directory, primarily intended to be used with nicknames, but could
  be used with affiliations and the like.  Because the name field is used in
  more than one place (such as email notifications), it is important that these
  additional strings not be placed in the name field, but be specified
  separately.
  
  Review: https://reviewboard.asterisk.org/r/2244/
................


git-svn-id: https://origsvn.digium.com/svn/asterisk/team/mmichelson/threadpool@378422 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Automerge script
2013-01-03 16:19:40 +00:00
parent b375abae50
commit 01250e2585
4 changed files with 113 additions and 26 deletions

View File

@@ -87,6 +87,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
argument will be used for the number of characters the user should enter.</para>
<argument name="n" required="true" />
</option>
<option name="a">
<para>Allow the caller to additionally enter an alias for a user in the
directory. This option must be specified in addition to the
<literal>f</literal>, <literal>l</literal>, or <literal>b</literal>
option.</para>
</option>
<option name="m">
<para>Instead of reading each name sequentially and asking for
confirmation, create a menu of up to 8 names.</para>
@@ -135,6 +141,7 @@ enum {
OPT_LISTBYEITHER = OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME,
OPT_PAUSE = (1 << 5),
OPT_NOANSWER = (1 << 6),
OPT_ALIAS = (1 << 7),
};
enum {
@@ -164,6 +171,7 @@ AST_APP_OPTIONS(directory_app_options, {
AST_APP_OPTION('v', OPT_FROMVOICEMAIL),
AST_APP_OPTION('m', OPT_SELECTFROMMENU),
AST_APP_OPTION('n', OPT_NOANSWER),
AST_APP_OPTION('a', OPT_ALIAS),
});
static int compare(const char *text, const char *template)
@@ -427,6 +435,8 @@ static int select_item_menu(struct ast_channel *chan, struct directory_item **it
return 0;
}
AST_THREADSTORAGE(commonbuf);
static struct ast_config *realtime_directory(char *context)
{
struct ast_config *cfg;
@@ -436,8 +446,12 @@ static struct ast_config *realtime_directory(char *context)
char *mailbox;
const char *fullname;
const char *hidefromdir, *searchcontexts = NULL;
char tmp[100];
struct ast_flags config_flags = { 0 };
struct ast_str *tmp = ast_str_thread_get(&commonbuf, 100);
if (!tmp) {
return NULL;
}
/* Load flat file config. */
cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
@@ -472,6 +486,7 @@ static struct ast_config *realtime_directory(char *context)
mailbox = NULL;
while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) {
struct ast_variable *alias;
const char *ctx = ast_variable_retrieve(rtdata, mailbox, "context");
fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
@@ -480,7 +495,14 @@ static struct ast_config *realtime_directory(char *context)
/* Skip hidden */
continue;
}
snprintf(tmp, sizeof(tmp), "no-password,%s", S_OR(fullname, ""));
ast_str_set(&tmp, 0, "no-password,%s", S_OR(fullname, ""));
if (ast_variable_retrieve(rtdata, mailbox, "alias")) {
for (alias = ast_variable_browse(rtdata, mailbox); alias; alias = alias->next) {
if (!strcasecmp(alias->name, "alias")) {
ast_str_append(&tmp, 0, "|alias=%s", alias->value);
}
}
}
/* Does the context exist within the config file? If not, make one */
if (!(cat = ast_category_get(cfg, ctx))) {
@@ -495,7 +517,7 @@ static struct ast_config *realtime_directory(char *context)
ast_category_append(cfg, cat);
}
if ((var = ast_variable_new(mailbox, tmp, ""))) {
if ((var = ast_variable_new(mailbox, ast_str_buffer(tmp), ""))) {
ast_variable_append(cat, var);
} else {
ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
@@ -556,20 +578,26 @@ typedef AST_LIST_HEAD_NOLOCK(, directory_item) itemlist;
static int search_directory_sub(const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
{
struct ast_variable *v;
char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat;
struct ast_str *buf = ast_str_thread_get(&commonbuf, 100);
char *pos, *bufptr, *cat, *alias;
struct directory_item *item;
int res;
if (!buf) {
return -1;
}
ast_debug(2, "Pattern: %s\n", ext);
for (v = ast_variable_browse(vmcfg, context); v; v = v->next) {
/* Ignore hidden */
if (strcasestr(v->value, "hidefromdir=yes"))
if (strcasestr(v->value, "hidefromdir=yes")) {
continue;
}
ast_copy_string(buf, v->value, sizeof(buf));
bufptr = buf;
ast_str_set(&buf, 0, "%s", v->value);
bufptr = ast_str_buffer(buf);
/* password,Full Name,email,pager,options */
strsep(&bufptr, ",");
@@ -587,11 +615,23 @@ static int search_directory_sub(const char *context, struct ast_config *vmcfg, s
if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
res = check_match(&item, context, pos, v->name, ext, 1 /* use_first_name */);
}
if (!res && ast_test_flag(&flags, OPT_ALIAS) && (alias = strcasestr(bufptr, "alias="))) {
char *a;
ast_debug(1, "Found alias: %s\n", alias);
while ((a = strsep(&alias, "|"))) {
if (!strncasecmp(a, "alias=", 6)) {
if ((res = check_match(&item, context, a + 6, v->name, ext, 1))) {
break;
}
}
}
}
if (!res)
if (!res) {
continue;
else if (res < 0)
} else if (res < 0) {
return -1;
}
AST_LIST_INSERT_TAIL(alist, item, entry);
}
@@ -599,15 +639,18 @@ static int search_directory_sub(const char *context, struct ast_config *vmcfg, s
if (ucfg) {
for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
const char *position;
if (!strcasecmp(cat, "general"))
if (!strcasecmp(cat, "general")) {
continue;
if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory")))
}
if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) {
continue;
}
/* Find all candidate extensions */
position = ast_variable_retrieve(ucfg, cat, "fullname");
if (!position)
if (!(position = ast_variable_retrieve(ucfg, cat, "fullname"))) {
continue;
}
res = 0;
if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
@@ -616,11 +659,20 @@ static int search_directory_sub(const char *context, struct ast_config *vmcfg, s
if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
res = check_match(&item, context, position, cat, ext, 1 /* use_first_name */);
}
if (!res && ast_test_flag(&flags, OPT_ALIAS)) {
struct ast_variable *alias;
for (alias = ast_variable_browse(ucfg, cat); alias; alias = alias->next) {
if (!strcasecmp(v->name, "alias") && (res = check_match(&item, context, v->value, cat, ext, 1))) {
break;
}
}
}
if (!res)
if (!res) {
continue;
else if (res < 0)
} else if (res < 0) {
return -1;
}
AST_LIST_INSERT_TAIL(alist, item, entry);
}

View File

@@ -282,6 +282,10 @@ sendvoicemail=yes ; Allow the user to compose and send a voicemail while inside
; This is intended for use with users who wish to receive their
; voicemail ONLY by email. Note: "deletevoicemail" is provided as an
; equivalent option for Realtime configuration.
; alias=Bongo ; Use this additional string for comparison while looking
; for a match in the Directory application. This option
; may be specified multiple times to specify additional
; strings [per-mailbox only]
; volgain=0.0 ; Emails bearing the voicemail may arrive in a volume too
; quiet to be heard. This parameter allows you to specify how
; much gain to add to the message when sending a voicemail.

View File

@@ -10,6 +10,8 @@ CREATE TABLE voicemail (
password CHAR(80) NOT NULL,
-- Used in email and for Directory app
fullname CHAR(80),
-- Used for Directory app
alias CHAR(80),
-- Email address (will get sound file if attach=yes)
email CHAR(80),
-- Email address (won't get sound file)

View File

@@ -928,7 +928,7 @@ static iks* xmpp_pubsub_iq_create(struct ast_xmpp_client *client, const char *ty
* \return iks *
*/
static iks* xmpp_pubsub_build_publish_skeleton(struct ast_xmpp_client *client, const char *node,
const char *event_type)
const char *event_type, unsigned int cachable)
{
RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
iks *request, *pubsub, *publish, *item;
@@ -944,6 +944,22 @@ static iks* xmpp_pubsub_build_publish_skeleton(struct ast_xmpp_client *client, c
item = iks_insert(publish, "item");
iks_insert_attrib(item, "id", node);
if (cachable == AST_DEVSTATE_NOT_CACHABLE) {
iks *options, *x, *field_form_type, *field_persist;
options = iks_insert(pubsub, "publish-options");
x = iks_insert(options, "x");
iks_insert_attrib(x, "xmlns", "jabber:x:data");
iks_insert_attrib(x, "type", "submit");
field_form_type = iks_insert(x, "field");
iks_insert_attrib(field_form_type, "var", "FORM_TYPE");
iks_insert_attrib(field_form_type, "type", "hidden");
iks_insert_cdata(iks_insert(field_form_type, "value"), "http://jabber.org/protocol/pubsub#publish-options", 0);
field_persist = iks_insert(x, "field");
iks_insert_attrib(field_persist, "var", "pubsub#persist_items");
iks_insert_cdata(iks_insert(field_persist, "value"), "0", 1);
}
return item;
}
@@ -1120,7 +1136,7 @@ static void xmpp_pubsub_publish_mwi(struct ast_xmpp_client *client, const char *
snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context);
if (!(request = xmpp_pubsub_build_publish_skeleton(client, full_mailbox, "message_waiting"))) {
if (!(request = xmpp_pubsub_build_publish_skeleton(client, full_mailbox, "message_waiting", AST_DEVSTATE_CACHABLE))) {
return;
}
@@ -1144,13 +1160,13 @@ static void xmpp_pubsub_publish_mwi(struct ast_xmpp_client *client, const char *
* \return void
*/
static void xmpp_pubsub_publish_device_state(struct ast_xmpp_client *client, const char *device,
const char *device_state)
const char *device_state, unsigned int cachable)
{
RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
iks *request, *state;
char eid_str[20];
char eid_str[20], cachable_str[2];
if (!cfg || !cfg->global || !(request = xmpp_pubsub_build_publish_skeleton(client, device, "device_state"))) {
if (!cfg || !cfg->global || !(request = xmpp_pubsub_build_publish_skeleton(client, device, "device_state", cachable))) {
return;
}
@@ -1166,6 +1182,8 @@ static void xmpp_pubsub_publish_device_state(struct ast_xmpp_client *client, con
state = iks_insert(request, "state");
iks_insert_attrib(state, "xmlns", "http://asterisk.org");
iks_insert_attrib(state, "eid", eid_str);
snprintf(cachable_str, sizeof(cachable_str), "%u", cachable);
iks_insert_attrib(state, "cachable", cachable_str);
iks_insert_cdata(state, device_state, strlen(device_state));
ast_xmpp_client_send(client, iks_root(request));
iks_delete(request);
@@ -1208,6 +1226,7 @@ static void xmpp_pubsub_devstate_cb(const struct ast_event *ast_event, void *dat
{
struct ast_xmpp_client *client = data;
const char *device, *device_state;
unsigned int cachable;
if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) {
/* If the event didn't originate from this server, don't send it back out. */
@@ -1217,7 +1236,8 @@ static void xmpp_pubsub_devstate_cb(const struct ast_event *ast_event, void *dat
device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE);
device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE));
xmpp_pubsub_publish_device_state(client, device, device_state);
cachable = ast_event_get_ie_uint(ast_event, AST_EVENT_IE_CACHABLE);
xmpp_pubsub_publish_device_state(client, device, device_state, cachable);
}
/*!
@@ -1301,11 +1321,12 @@ static void xmpp_pubsub_subscribe(struct ast_xmpp_client *client, const char *no
*/
static int xmpp_pubsub_handle_event(void *data, ikspak *pak)
{
char *item_id, *device_state, *context;
char *item_id, *device_state, *context, *cachable_str;
int oldmsgs, newmsgs;
iks *item, *item_content;
struct ast_eid pubsub_eid;
struct ast_event *event;
unsigned int cachable = AST_DEVSTATE_CACHABLE;
item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item");
if (!item) {
ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n");
@@ -1320,6 +1341,9 @@ static int xmpp_pubsub_handle_event(void *data, ikspak *pak)
}
if (!strcasecmp(iks_name(item_content), "state")) {
device_state = iks_find_cdata(item, "state");
if ((cachable_str = iks_find_cdata(item, "cachable"))) {
sscanf(cachable_str, "%30d", &cachable);
}
if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE,
AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE,
AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID,
@@ -1344,7 +1368,13 @@ static int xmpp_pubsub_handle_event(void *data, ikspak *pak)
iks_name(item_content));
return IKS_FILTER_EAT;
}
ast_event_queue_and_cache(event);
if (cachable == AST_DEVSTATE_CACHABLE) {
ast_event_queue_and_cache(event);
} else {
ast_event_queue(event);
}
return IKS_FILTER_EAT;
}
@@ -1846,7 +1876,7 @@ static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, ch
{
RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
char *aux = NULL, *parse = NULL;
char *parse = NULL;
int timeout, jidlen, resourcelen, found = 0;
struct timeval start;
long diff = 0;
@@ -1960,7 +1990,7 @@ static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, ch
continue;
}
found = 1;
aux = ast_strdupa(message->message);
ast_copy_string(buf, message->message, buflen);
AST_LIST_REMOVE_CURRENT(list);
xmpp_message_destroy(message);
break;
@@ -1984,7 +2014,6 @@ static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, ch
ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid);
return -1;
}
ast_copy_string(buf, aux, buflen);
return 0;
}