jabberd2  2.3.4
mod_privacy.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #include "sm.h"
22 
30 static int ns_PRIVACY = 0;
31 static int ns_BLOCKING = 0;
32 
33 typedef struct zebra_st *zebra_t;
34 typedef struct zebra_list_st *zebra_list_t;
35 typedef struct zebra_item_st *zebra_item_t;
36 
37 typedef enum {
43 
44 typedef enum {
45  block_NONE = 0x00,
46  block_MESSAGE = 0x01,
47  block_PRES_IN = 0x02,
49  block_IQ = 0x08
51 
53 struct zebra_st {
55 
56  zebra_list_t def;
57 };
58 
59 struct zebra_list_st {
61 
62  char *name;
63 
64  zebra_item_t items, last;
65 };
66 
67 struct zebra_item_st {
69 
71 
72  char *group;
73 
74  int to;
75  int from;
76 
77  int deny; /* 0 = allow, 1 = deny */
78 
79  int order;
80 
82 
83  zebra_item_t next, prev;
84 };
85 
86 typedef struct privacy_st {
87  /* currently active list */
88  zebra_list_t active;
89 
90  /* was blocklist requested */
91  int blocklist;
92 } *privacy_t;
93 
94 /* union for xhash_iter_get to comply with strict-alias rules for gcc3 */
95 union xhashv
96 {
97  void **val;
98  zebra_list_t *z_val;
99 };
100 
101 static void _privacy_free_z(zebra_t z) {
102  zebra_list_t zlist;
103  union xhashv xhv;
104 
105  log_debug(ZONE, "freeing zebra ctx");
106 
107  if(xhash_iter_first(z->lists))
108  do {
109  xhv.z_val = &zlist;
110  xhash_iter_get(z->lists, NULL, NULL, xhv.val);
111  pool_free(zlist->p);
112  } while(xhash_iter_next(z->lists));
113 
114  xhash_free(z->lists);
115  free(z);
116 }
117 
118 static void _privacy_user_free(zebra_t *z) {
119  if(*z != NULL)
120  _privacy_free_z(*z);
121 }
122 
124  module_t mod = mi->mod;
125  zebra_t z;
126  os_t os;
127  os_object_t o;
128  zebra_list_t zlist;
129  pool_t p;
130  zebra_item_t zitem, scan;
131  char *str;
132 
133  log_debug(ZONE, "loading privacy lists for %s", jid_user(user->jid));
134 
135  /* free if necessary */
136  z = user->module_data[mod->index];
137  if(z != NULL)
138  _privacy_free_z(z);
139 
140  z = (zebra_t) calloc(1, sizeof(struct zebra_st));
141 
142  z->lists = xhash_new(101);
143 
144  user->module_data[mod->index] = z;
145 
146  pool_cleanup(user->p, (void (*))(void *) _privacy_user_free, &(user->module_data[mod->index]));
147 
148  /* pull the whole lot */
149  if(storage_get(user->sm->st, "privacy-items", jid_user(user->jid), NULL, &os) == st_SUCCESS) {
150  if(os_iter_first(os))
151  do {
152  o = os_iter_object(os);
153 
154  /* list name */
155  if(!os_object_get_str(os, o, "list", &str)) {
156  log_debug(ZONE, "item with no list field, skipping");
157  continue;
158  }
159 
160  log_debug(ZONE, "got item for list %s", str);
161 
162  zlist = xhash_get(z->lists, str);
163 
164  /* new list */
165  if(zlist == NULL) {
166  log_debug(ZONE, "creating list %s", str);
167 
168  p = pool_new();
169 
170  zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st));
171 
172  zlist->p = p;
173  zlist->name = pstrdup(p, str);
174 
175  xhash_put(z->lists, zlist->name, (void *) zlist);
176  }
177 
178  /* new item */
179  zitem = (zebra_item_t) pmalloco(zlist->p, sizeof(struct zebra_item_st));
180 
181  /* item type */
182  if(os_object_get_str(os, o, "type", &str))
183  switch(str[0]) {
184  case 'j':
185  zitem->type = zebra_JID;
186  break;
187 
188  case 'g':
189  zitem->type = zebra_GROUP;
190  break;
191 
192  case 's':
193  zitem->type = zebra_S10N;
194  break;
195  }
196 
197  /* item value, according to type */
198  if(zitem->type != zebra_NONE) {
199  if(!os_object_get_str(os, o, "value", &str)) {
200  log_debug(ZONE, "no value on non-fall-through item, dropping this item");
201  continue;
202  }
203 
204  switch(zitem->type) {
205 
206  case zebra_JID:
207  zitem->jid = jid_new(str, strlen(str));
208  if(zitem->jid == NULL) {
209  log_debug(ZONE, "invalid jid '%s' on item, dropping this item", str);
210  continue;
211  }
212 
213  pool_cleanup(zlist->p, (void *) jid_free, zitem->jid);
214 
215  log_debug(ZONE, "jid item with value '%s'", jid_full(zitem->jid));
216 
217  break;
218 
219  case zebra_GROUP:
220  zitem->group = pstrdup(zlist->p, str);
221 
222  log_debug(ZONE, "group item with value '%s'", zitem->group);
223 
224  break;
225 
226  case zebra_S10N:
227  if(strcmp(str, "to") == 0)
228  zitem->to = 1;
229  else if(strcmp(str, "from") == 0)
230  zitem->from = 1;
231  else if(strcmp(str, "both") == 0)
232  zitem->to = zitem->from = 1;
233  else if(strcmp(str, "none") != 0) {
234  log_debug(ZONE, "invalid value '%s' on s10n item, dropping this item", str);
235  continue;
236  }
237 
238  log_debug(ZONE, "s10n item with value '%s' (to %d from %d)", str, zitem->to, zitem->from);
239 
240  break;
241 
242  case zebra_NONE:
243  /* can't get here */
244  break;
245  }
246  }
247 
248  /* action */
249  os_object_get_bool(os, o, "deny", &zitem->deny);
250  if(zitem->deny) {
251  log_debug(ZONE, "deny rule");
252  } else {
253  log_debug(ZONE, "accept rule");
254  }
255 
256  os_object_get_int(os, o, "order", &(zitem->order));
257  log_debug(ZONE, "order %d", zitem->order);
258 
259  os_object_get_int(os, o, "block", (int*) &(zitem->block));
260  log_debug(ZONE, "block 0x%x", zitem->block);
261 
262  /* insert it */
263  for(scan = zlist->items; scan != NULL; scan = scan->next)
264  if(zitem->order < scan->order)
265  break;
266 
267  /* we're >= everyone, add us to the end */
268  if(scan == NULL) {
269  if(zlist->last == NULL)
270  zlist->items = zlist->last = zitem;
271  else {
272  zlist->last->next = zitem;
273  zitem->prev = zlist->last;
274  zlist->last = zitem;
275  }
276  }
277 
278  /* insert just before scan */
279  else {
280  if(zlist->items == scan) {
281  zitem->next = zlist->items;
282  zlist->items = zitem;
283  scan->prev = zitem;
284  } else {
285  zitem->next = scan;
286  zitem->prev = scan->prev;
287  scan->prev->next = zitem;
288  scan->prev = zitem;
289  }
290  }
291  } while(os_iter_next(os));
292 
293  os_free(os);
294  }
295 
296  /* default list */
297  if(storage_get(user->sm->st, "privacy-default", jid_user(user->jid), NULL, &os) == st_SUCCESS) {
298  if(os_iter_first(os))
299  do {
300  o = os_iter_object(os);
301 
302  if(os_object_get_str(os, o, "default", &str)) {
303  z->def = (zebra_list_t) xhash_get(z->lists, str);
304  if(z->def == NULL) {
305  log_debug(ZONE, "storage says the default list for %s is %s, but it doesn't exist!", jid_user(user->jid), str);
306  } else {
307  log_debug(ZONE, "user %s has default list %s", jid_user(user->jid), str);
308  }
309  }
310  } while(os_iter_next(os));
311 
312  os_free(os);
313  }
314 
315  return 0;
316 }
317 
319 static int _privacy_action(user_t user, zebra_list_t zlist, jid_t jid, pkt_type_t ptype, int in) {
320  zebra_item_t scan;
321  int match, i;
322  item_t ritem;
323  char domres[2048];
324 
325  log_debug(ZONE, "running match on list %s for %s (packet type 0x%x) (%s)", zlist->name, jid_full(jid), ptype, in ? "incoming" : "outgoing");
326 
327  /* loop over the list, trying to find a match */
328  for(scan = zlist->items; scan != NULL; scan = scan->next) {
329  match = 0;
330 
331  switch(scan->type) {
332  case zebra_NONE:
333  /* fall through, all packets match this */
334  match = 1;
335  break;
336 
337  case zebra_JID:
338  snprintf(domres, sizeof(domres) / sizeof(domres[0]), "%s/%s", jid->domain, jid->resource);
339 
340  /* jid check - match node@dom/res, then node@dom, then dom/resource, then dom */
341  if(jid_compare_full(scan->jid, jid) == 0 ||
342  strcmp(jid_full(scan->jid), jid_user(jid)) == 0 ||
343  strcmp(jid_full(scan->jid), domres) == 0 ||
344  strcmp(jid_full(scan->jid), jid->domain) == 0)
345  match = 1;
346 
347  break;
348 
349  case zebra_GROUP:
350  /* roster group check - get the roster item, node@dom/res, then node@dom, then dom */
351  ritem = xhash_get(user->roster, jid_full(jid));
352  if(ritem == NULL) ritem = xhash_get(user->roster, jid_user(jid));
353  if(ritem == NULL) ritem = xhash_get(user->roster, jid->domain);
354 
355  /* got it, do the check */
356  if(ritem != NULL)
357  for(i = 0; i < ritem->ngroups; i++)
358  if(strcmp(scan->group, ritem->groups[i]) == 0)
359  match = 1;
360 
361  break;
362 
363  case zebra_S10N:
364  /* roster item check - get the roster item, node@dom/res, then node@dom, then dom */
365  ritem = xhash_get(user->roster, jid_full(jid));
366  if(ritem == NULL) ritem = xhash_get(user->roster, jid_user(jid));
367  if(ritem == NULL) ritem = xhash_get(user->roster, jid->domain);
368 
369  /* got it, do the check */
370  if(ritem != NULL)
371  if(scan->to == ritem->to && scan->from == ritem->from)
372  match = 1;
373 
374  break;
375  }
376 
377  /* if we matched a rule, we have to do packet block matching */
378  if(match) {
379  /* no packet blocking, matching done */
380  if(scan->block == block_NONE)
381  return scan->deny;
382 
383  /* incoming checks block_MESSAGE, block_PRES_IN and block_IQ */
384  if(in) {
385  if(ptype & pkt_MESSAGE && scan->block & block_MESSAGE)
386  return scan->deny;
387  if(ptype & pkt_PRESENCE && scan->block & block_PRES_IN)
388  return scan->deny;
389  if(ptype & pkt_IQ && scan->block & block_IQ)
390  return scan->deny;
391  } else if((ptype & pkt_PRESENCE && scan->block & block_PRES_OUT && ptype != pkt_PRESENCE_PROBE) ||
392  (ptype & pkt_MESSAGE && scan->block & block_MESSAGE)) {
393  /* outgoing check, block_PRES_OUT */
394  /* XXX and block_MESSAGE for XEP-0191 while it violates XEP-0016 */
395  return scan->deny;
396  }
397  }
398  }
399 
400  /* didn't match the list, so allow */
401  return 0;
402 }
403 
406  module_t mod = mi->mod;
407  user_t user;
408  zebra_t z;
409  sess_t sess = NULL;
410  zebra_list_t zlist = NULL;
411 
412  /* if its coming to the sm, let it in */
413  if(pkt->to == NULL || pkt->to->node[0] == '\0')
414  return mod_PASS;
415 
416  /* get the user */
417  user = user_load(mod->mm->sm, pkt->to);
418  if(user == NULL) {
419  log_debug(ZONE, "no user %s, passing packet", jid_user(pkt->to));
420  return mod_PASS;
421  }
422 
423  /* get our lists */
424  z = (zebra_t) user->module_data[mod->index];
425 
426  /* find a session */
427  if(*pkt->to->resource != '\0')
428  sess = sess_match(user, pkt->to->resource);
429 
430  /* didn't match a session, so use the top session */
431  if(sess == NULL)
432  sess = user->top;
433 
434  /* get the active list for the session */
435  if(sess != NULL && sess->module_data[mod->index] != NULL)
436  zlist = ((privacy_t) sess->module_data[mod->index])->active;
437 
438  /* no active list, so use the default list */
439  if(zlist == NULL)
440  zlist = z->def;
441 
442  /* no list, so allow everything */
443  if(zlist == NULL)
444  return mod_PASS;
445 
446  /* figure out the action */
447  if(_privacy_action(user, zlist, pkt->from, pkt->type, 1) == 0)
448  return mod_PASS;
449 
450  /* deny */
451  log_debug(ZONE, "denying incoming packet based on privacy policy");
452 
453  /* iqs get special treatment */
454  if(pkt->type == pkt_IQ || pkt->type == pkt_IQ_SET)
456 
457  /* drop it */
458  pkt_free(pkt);
459  return mod_HANDLED;
460 }
461 
464  module_t mod = mi->mod;
465  user_t user;
466  zebra_t z;
467  sess_t sess = NULL;
468  zebra_list_t zlist = NULL;
469  int err, ns;
470 
471  /* if its coming from the sm, let it go */
472  if(pkt->from == NULL || pkt->from->node[0] == '\0')
473  return mod_PASS;
474 
475  /* get the user */
476  user = user_load(mod->mm->sm, pkt->from);
477  if(user == NULL) {
478  log_debug(ZONE, "no user %s, passing packet", jid_user(pkt->to));
479  return mod_PASS;
480  }
481 
482  /* get our lists */
483  z = (zebra_t) user->module_data[mod->index];
484 
485  /* find a session */
486  if(*pkt->from->resource != '\0')
487  sess = sess_match(user, pkt->from->resource);
488 
489  /* get the active list for the session */
490  if(sess != NULL && sess->module_data[mod->index] != NULL)
491  zlist = ((privacy_t) sess->module_data[mod->index])->active;
492 
493  /* no active list, so use the default list */
494  if(zlist == NULL)
495  zlist = z->def;
496 
497  /* no list, so allow everything */
498  if(zlist == NULL)
499  return mod_PASS;
500 
501  /* figure out the action */
502  if(_privacy_action(user, zlist, pkt->to, pkt->type, 0) == 0)
503  return mod_PASS;
504 
505  /* deny */
506  log_debug(ZONE, "denying outgoing packet based on privacy policy");
507 
508  /* messages get special treatment */
509  if(pkt->type & pkt_MESSAGE) {
510  /* hack the XEP-0191 error in */
512  err = nad_find_elem(pkt->nad, 1, -1, "error", 1);
513  ns = nad_add_namespace(pkt->nad, urn_BLOCKING_ERR, NULL);
514  nad_insert_elem(pkt->nad, err, ns, "blocked", NULL);
515  pkt_sess(pkt, sess);
516  return mod_HANDLED;
517  }
518 
519  /* drop it */
520  pkt_free(pkt);
521  return mod_HANDLED;
522 }
523 
525 static void _privacy_result_builder(xht zhash, const char *name, void *val, void *arg) {
526  zebra_list_t zlist = (zebra_list_t) val;
527  pkt_t pkt = (pkt_t) arg;
528  int ns, query, list, item;
529  zebra_item_t zitem;
530  char order[14];
531 
532  ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL);
533  query = nad_find_elem(pkt->nad, 1, ns, "query", 1);
534 
535  list = nad_insert_elem(pkt->nad, query, ns, "list", NULL);
536  nad_set_attr(pkt->nad, list, -1, "name", zlist->name, 0);
537 
538  /* run through the items and build the nad */
539  for(zitem = zlist->items; zitem != NULL; zitem = zitem->next) {
540  item = nad_insert_elem(pkt->nad, list, ns, "item", NULL);
541 
542  switch(zitem->type) {
543  case zebra_JID:
544  nad_set_attr(pkt->nad, item, -1, "type", "jid", 0);
545  nad_set_attr(pkt->nad, item, -1, "value", jid_full(zitem->jid), 0);
546  break;
547 
548  case zebra_GROUP:
549  nad_set_attr(pkt->nad, item, -1, "type", "group", 0);
550  nad_set_attr(pkt->nad, item, -1, "value", zitem->group, 0);
551  break;
552 
553  case zebra_S10N:
554  nad_set_attr(pkt->nad, item, -1, "type", "subscription", 0);
555 
556  if(zitem->to == 1 && zitem->from == 1)
557  nad_set_attr(pkt->nad, item, -1, "value", "both", 4);
558  else if(zitem->to == 1)
559  nad_set_attr(pkt->nad, item, -1, "value", "to", 2);
560  else if(zitem->from == 1)
561  nad_set_attr(pkt->nad, item, -1, "value", "from", 4);
562  else
563  nad_set_attr(pkt->nad, item, -1, "value", "none", 4);
564 
565  break;
566 
567  case zebra_NONE:
568  break;
569  }
570 
571  if(zitem->deny)
572  nad_set_attr(pkt->nad, item, -1, "action", "deny", 4);
573  else
574  nad_set_attr(pkt->nad, item, -1, "action", "allow", 5);
575 
576  snprintf(order, 14, "%d", zitem->order);
577  order[13] = '\0';
578 
579  nad_set_attr(pkt->nad, item, -1, "order", order, 0);
580 
581  if(zitem->block & block_MESSAGE)
582  nad_insert_elem(pkt->nad, item, ns, "message", NULL);
583  if(zitem->block & block_PRES_IN)
584  nad_insert_elem(pkt->nad, item, ns, "presence-in", NULL);
585  if(zitem->block & block_PRES_OUT)
586  nad_insert_elem(pkt->nad, item, ns, "presence-out", NULL);
587  if(zitem->block & block_IQ)
588  nad_insert_elem(pkt->nad, item, ns, "iq", NULL);
589  }
590 }
591 
593 static void _privacy_lists_result_builder(const char *name, int namelen, void *val, void *arg) {
594  zebra_list_t zlist = (zebra_list_t) val;
595  pkt_t pkt = (pkt_t) arg;
596  int ns, query, list;
597 
598  ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL);
599  query = nad_find_elem(pkt->nad, 1, ns, "query", 1);
600 
601  list = nad_insert_elem(pkt->nad, query, ns, "list", NULL);
602  nad_set_attr(pkt->nad, list, -1, "name", zlist->name, 0);
603 }
604 
608 static void _unblock_jid(user_t user, storage_t st, zebra_list_t zlist, jid_t jid) {
609  char filter[1024];
610  zebra_item_t scan;
611  sess_t sscan;
612  jid_t notify_jid = NULL;
613 
614  for(scan = zlist->items; scan != NULL; scan = scan->next) {
615  if(scan->type == zebra_JID && scan->deny && (jid == NULL || jid_compare_full(scan->jid, jid) == 0)) {
616  if(zlist->items == scan) {
617  zlist->items = scan->next;
618  if(zlist->items != NULL)
619  zlist->items->prev = NULL;
620  } else {
621  assert(scan->prev != NULL);
622  scan->prev->next = scan->next;
623  if(scan->next != NULL)
624  scan->next->prev = scan->prev;
625  }
626 
627  if (zlist->last == scan)
628  zlist->last = scan->prev;
629 
630  /* and from the storage */
631  sprintf(filter, "(&(list=%zu:%s)(type=3:jid)(value=%zu:%s))",
632  strlen(urn_BLOCKING), urn_BLOCKING, strlen(jid_full(scan->jid)), jid_full(scan->jid));
633  storage_delete(st, "privacy-items", jid_user(user->jid), filter);
634 
635  /* set jid for notify */
636  notify_jid = scan->jid;
637  }
638 
639  /* update unblocked contact with presence information of all sessions */
640 
641  /* XXX NOTE !!! There is a possibility that we notify more than once
642  * if user edited the privacy list manually, not with XEP-0191.
643  * Well... We're going to live with it. ;-) */
644  if(notify_jid != NULL && pres_trust(user, notify_jid))
645  for(sscan = user->sessions; sscan != NULL; sscan = sscan->next) {
646  /* do not update if session is not available,
647  * we sent presence direct or got error bounce */
648  if(!sscan->available || jid_search(sscan->A, notify_jid) || jid_search(sscan->E, notify_jid))
649  continue;
650 
651  log_debug(ZONE, "updating unblocked %s with presence from %s", jid_full(notify_jid), jid_full(sscan->jid));
652  pkt_router(pkt_dup(sscan->pres, jid_full(notify_jid), jid_full(sscan->jid)));
653  }
654  }
655 }
656 
659  module_t mod = mi->mod;
660  int ns, query, list, name, active, def, item, type, value, action, order, blocking, jid, push = 0;
661  char corder[14], str[256], filter[1024];
662  zebra_t z;
663  zebra_list_t zlist, old;
664  pool_t p;
665  zebra_item_t zitem, scan;
666  sess_t sscan;
667  jid_t jidt;
668  pkt_t result;
669  os_t os;
670  os_object_t o;
671  st_ret_t ret;
672 
673  /* we only want to play with iq:privacy and urn:xmpp:blocking packets */
674  if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || (pkt->ns != ns_PRIVACY && pkt->ns != ns_BLOCKING))
675  return mod_PASS;
676 
677  /* if it has a to, throw it out */
678  if(pkt->to != NULL)
679  return -stanza_err_BAD_REQUEST;
680 
681  /* get our lists */
682  z = (zebra_t) sess->user->module_data[mod->index];
683 
684  /* create session privacy description */
685  if(sess->module_data[mod->index] == NULL)
686  sess->module_data[mod->index] = (void *) pmalloco(sess->p, sizeof(struct privacy_st));
687 
688  /* handle XEP-0191: Simple Communications Blocking
689  * as simplified frontend to default privacy list */
690  if(pkt->ns == ns_BLOCKING) {
691  if(pkt->type == pkt_IQ_SET) {
692  /* find out what to do */
693  int block;
694  ns = nad_find_scoped_namespace(pkt->nad, urn_BLOCKING, NULL);
695  blocking = nad_find_elem(pkt->nad, 1, ns, "block", 1);
696  if(blocking >= 0)
697  block = 1;
698  else {
699  blocking = nad_find_elem(pkt->nad, 1, ns, "unblock", 1);
700  if(blocking >= 0)
701  block = 0;
702  else
703  return -stanza_err_BAD_REQUEST;
704  }
705 
706  /* if there is no default list, create one */
707  if(!z->def) {
708  /* remove any previous one */
709  if((zlist = xhash_get(z->lists, urn_BLOCKING))) {
710  pool_free(zlist->p);
711  sprintf(filter, "(list=%zu:%s)", strlen(urn_BLOCKING), urn_BLOCKING);
712  storage_delete(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), filter);
713  }
714 
715  /* create new zebra list with name 'urn:xmpp:blocking' */
716  p = pool_new();
717  zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st));
718  zlist->p = p;
719  zlist->name = pstrdup(p, urn_BLOCKING);
720  xhash_put(z->lists, zlist->name, (void *) zlist);
721 
722  /* make it default */
723  z->def = zlist;
724 
725  /* and in the storage */
726  os = os_new();
727  o = os_object_new(os);
728  os_object_put(o, "default", zlist->name, os_type_STRING);
729  ret = storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os);
730  os_free(os);
731  if(ret != st_SUCCESS)
733 
734  log_debug(ZONE, "blocking created '%s' privacy list and set it default", zlist->name);
735  } else {
736  /* use the default one */
737  zlist = z->def;
738  }
739  /* activate this list */
740  ((privacy_t) sess->module_data[mod->index])->active = zlist;
741  log_debug(ZONE, "session '%s' has now active list '%s'", jid_full(sess->jid), zlist->name);
742 
743  item = nad_find_elem(pkt->nad, blocking, ns, "item", 1);
744  if(item < 0) {
745  if(block) {
746  /* cannot block unknown */
747  return -stanza_err_BAD_REQUEST;
748  } else {
749  /* unblock all */
750  _unblock_jid(sess->user, mod->mm->sm->st, zlist, NULL);
751 
752  /* mark to send blocklist push */
753  push = 1;
754  }
755  }
756 
757  /* loop over the items */
758  while(item >= 0) {
759  /* extract jid */
760  jid = nad_find_attr(pkt->nad, item, -1, "jid", 0);
761  if(jid < 0)
762  return -stanza_err_BAD_REQUEST;
763 
764  jidt = jid_new(NAD_AVAL(pkt->nad, jid), NAD_AVAL_L(pkt->nad, jid));
765  if(jidt == NULL)
766  return -stanza_err_BAD_REQUEST;
767 
768  /* find blockitem in the list */
769  for(scan = zlist->items; scan != NULL; scan = scan->next)
770  if(scan->type == zebra_JID && jid_compare_full(scan->jid, jidt) == 0)
771  break;
772 
773  /* take action */
774  if(block) {
775  if(scan != NULL && scan->deny && scan->block == block_NONE) {
776  push = 0;
777  } else {
778  /* first make us unavailable if user is on roster */
779  if(pres_trust(sess->user, jidt))
780  for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
781  /* do not update if session is not available,
782  * we sent presence direct or got error bounce */
783  if(!sscan->available || jid_search(sscan->A, jidt) || jid_search(sscan->E, jidt))
784  continue;
785 
786  log_debug(ZONE, "forcing unavailable to %s from %s after block", jid_full(jidt), jid_full(sscan->jid));
787  pkt_router(pkt_create(sess->user->sm, "presence", "unavailable", jid_full(jidt), jid_full(sscan->jid)));
788  }
789 
790  /* new item */
791  zitem = (zebra_item_t) pmalloco(zlist->p, sizeof(struct zebra_item_st));
792  zitem->type = zebra_JID;
793 
794  zitem->jid = jid_new(NAD_AVAL(pkt->nad, jid), NAD_AVAL_L(pkt->nad, jid));
795  pool_cleanup(zlist->p, (void *) jid_free, zitem->jid);
796  zitem->deny = 1;
797  zitem->block = block_NONE;
798 
799  /* insert it in front of list */
800  zitem->order = 0;
801  if(zlist->last == NULL) {
802  zlist->items = zlist->last = zitem;
803  } else {
804  zitem->next = zlist->items;
805  zlist->items->prev = zitem;
806  zlist->items = zitem;
807  }
808 
809  /* and into the storage backend */
810  os = os_new();
811  o = os_object_new(os);
812  os_object_put(o, "list", zlist->name, os_type_STRING);
813  os_object_put(o, "type", "jid", os_type_STRING);
814  os_object_put(o, "value", jid_full(zitem->jid), os_type_STRING);
815  os_object_put(o, "deny", &zitem->deny, os_type_BOOLEAN);
816  os_object_put(o, "order", &zitem->order, os_type_INTEGER);
817  os_object_put(o, "block", &zitem->block, os_type_INTEGER);
818  ret = storage_put(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), os);
819  os_free(os);
820  if(ret != st_SUCCESS) {
821  jid_free(jidt);
823  }
824 
825  /* mark to send blocklist push */
826  push = 1;
827  }
828  } else {
829  /* unblock action */
830  if(scan != NULL && scan->deny) {
831  /* remove all jid deny ocurrences from the privacy list */
832  _unblock_jid(sess->user, mod->mm->sm->st, zlist, jidt);
833 
834  /* mark to send blocklist push */
835  push = 1;
836  } else {
837  jid_free(jidt);
839  }
840  }
841 
842  jid_free(jidt);
843 
844  /* next item */
845  item = nad_find_elem(pkt->nad, item, ns, "item", 0);
846  }
847 
848  /* return empty result */
849  result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
850  pkt_id(pkt, result);
851  pkt_sess(result, sess);
852 
853  /* blocklist push */
854  if(push) {
855  for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
856  /* don't push to us or to anyone who hasn't requested blocklist */
857  if(sscan == sess || sscan->module_data[mod->index] == NULL || ((privacy_t) sscan->module_data[mod->index])->blocklist == 0)
858  continue;
859 
860  result = pkt_dup(pkt, jid_full(sscan->jid), NULL);
861  if(result->from != NULL) {
862  jid_free(result->from);
863  nad_set_attr(result->nad, 1, -1, "from", NULL, 0);
864  }
865  pkt_id_new(result);
866  pkt_sess(result, sscan);
867  }
868  }
869 
870  /* and done with request */
871  pkt_free(pkt);
872  return mod_HANDLED;
873  }
874 
875  /* it's a get */
876  ns = nad_find_scoped_namespace(pkt->nad, urn_BLOCKING, NULL);
877  blocking = nad_find_elem(pkt->nad, 1, ns, "blocklist", 1);
878  if(blocking < 0)
879  return -stanza_err_BAD_REQUEST;
880 
881  result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
882  pkt_id(pkt, result);
883  ns = nad_add_namespace(result->nad, urn_BLOCKING, NULL);
884  blocking = nad_insert_elem(result->nad, 1, ns, "blocklist", NULL);
885 
886  /* insert items only from the default list */
887  if(z->def != NULL) {
888  log_debug(ZONE, "blocking list is '%s'", z->def->name);
889  zlist = xhash_get(z->lists, z->def->name);
890  /* run through the items and build the nad */
891  for(zitem = zlist->items; zitem != NULL; zitem = zitem->next) {
892  /* we're interested in items type 'jid' with action 'deny' only */
893  if(zitem->type == zebra_JID && zitem->deny) {
894  item = nad_insert_elem(result->nad, blocking, -1, "item", NULL);
895  nad_set_attr(result->nad, item, -1, "jid", jid_full(zitem->jid), 0);
896  }
897  }
898 
899  /* mark that the blocklist was requested */
900  ((privacy_t) sess->module_data[mod->index])->blocklist = 1;
901  }
902 
903  /* give it to the session */
904  pkt_sess(result, sess);
905  pkt_free(pkt);
906  return mod_HANDLED;
907  }
908 
909  /* else handle XEP-0016: Privacy Lists */
910 
911  /* find the query */
912  ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL);
913  query = nad_find_elem(pkt->nad, 1, ns, "query", 1);
914  if(query < 0)
915  return -stanza_err_BAD_REQUEST;
916 
917  /* update lists or set the active list */
918  if(pkt->type == pkt_IQ_SET) {
919  /* find out what we're doing */
920  list = nad_find_elem(pkt->nad, query, ns, "list", 1);
921  active = nad_find_elem(pkt->nad, query, ns, "active", 1);
922  def = nad_find_elem(pkt->nad, query, ns, "default", 1);
923 
924  /* we need something to do, but we can't do it all at once */
925  if((list < 0 && active < 0 && def < 0) || (list >= 0 && (active >=0 || def >= 0)))
926  return -stanza_err_BAD_REQUEST;
927 
928  /* loop over any/all lists and store them */
929  if(list >= 0) {
930  /* only allowed to change one list at a time */
931  if(nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0)
932  return -stanza_err_BAD_REQUEST;
933 
934  /* get the list name */
935  name = nad_find_attr(pkt->nad, list, -1, "name", NULL);
936  if(name < 0) {
937  log_debug(ZONE, "no list name specified, failing request");
938  return -stanza_err_BAD_REQUEST;
939  }
940 
941  snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name));
942  str[255] = '\0';
943 
944  log_debug(ZONE, "updating list %s", str);
945 
946  /* make a new one */
947  p = pool_new();
948 
949  zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st));
950 
951  zlist->p = p;
952  zlist->name = pstrdup(p, str);
953 
954  os = os_new();
955 
956  /* loop over the items */
957  item = nad_find_elem(pkt->nad, list, ns, "item", 1);
958  while(item >= 0) {
959  /* extract things */
960  type = nad_find_attr(pkt->nad, item, -1, "type", 0);
961  value = nad_find_attr(pkt->nad, item, -1, "value", 0);
962  action = nad_find_attr(pkt->nad, item, -1, "action", 0);
963  order = nad_find_attr(pkt->nad, item, -1, "order", 0);
964 
965  /* sanity */
966  if(action < 0 || order < 0 || (type >= 0 && value < 0)) {
967  pool_free(p);
968  os_free(os);
969  return -stanza_err_BAD_REQUEST;
970  }
971 
972  /* new item */
973  zitem = (zebra_item_t) pmalloco(p, sizeof(struct zebra_item_st));
974 
975  /* have to store it too */
976  o = os_object_new(os);
977  os_object_put(o, "list", zlist->name, os_type_STRING);
978 
979  /* type & value */
980  if(type >= 0) {
981  if(NAD_AVAL_L(pkt->nad, type) == 3 && strncmp("jid", NAD_AVAL(pkt->nad, type), 3) == 0) {
982  zitem->type = zebra_JID;
983 
984  zitem->jid = jid_new(NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value));
985  if(zitem->jid == NULL) {
986  log_debug(ZONE, "invalid jid '%.*s', failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value));
987  pool_free(p);
988  os_free(os);
989  return -stanza_err_BAD_REQUEST;
990  }
991 
992  pool_cleanup(p, (void *) jid_free, zitem->jid);
993 
994  log_debug(ZONE, "jid item with value '%s'", jid_full(zitem->jid));
995 
996  os_object_put(o, "type", "jid", os_type_STRING);
997  os_object_put(o, "value", jid_full(zitem->jid), os_type_STRING);
998  }
999 
1000  else if(NAD_AVAL_L(pkt->nad, type) == 5 && strncmp("group", NAD_AVAL(pkt->nad, type), 5) == 0) {
1001  zitem->type = zebra_GROUP;
1002 
1003  zitem->group = pstrdupx(zlist->p, NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value));
1004 
1005  /* !!! check if the group exists */
1006 
1007  log_debug(ZONE, "group item with value '%s'", zitem->group);
1008 
1009  os_object_put(o, "type", "group", os_type_STRING);
1010  os_object_put(o, "value", zitem->group, os_type_STRING);
1011  }
1012 
1013  else if(NAD_AVAL_L(pkt->nad, type) == 12 && strncmp("subscription", NAD_AVAL(pkt->nad, type), 12) == 0) {
1014  zitem->type = zebra_S10N;
1015 
1016  os_object_put(o, "type", "subscription", os_type_STRING);
1017 
1018  if(NAD_AVAL_L(pkt->nad, value) == 2 && strncmp("to", NAD_AVAL(pkt->nad, value), 2) == 0) {
1019  zitem->to = 1;
1020  os_object_put(o, "value", "to", os_type_STRING);
1021  } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("from", NAD_AVAL(pkt->nad, value), 4) == 0) {
1022  zitem->from = 1;
1023  os_object_put(o, "value", "from", os_type_STRING);
1024  } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("both", NAD_AVAL(pkt->nad, value), 4) == 0) {
1025  zitem->to = zitem->from = 1;
1026  os_object_put(o, "value", "both", os_type_STRING);
1027  } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("none", NAD_AVAL(pkt->nad, value), 4) == 0)
1028  os_object_put(o, "value", "none", os_type_STRING);
1029  else {
1030  log_debug(ZONE, "invalid value '%.*s' on s10n item, failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value));
1031  pool_free(p);
1032  os_free(os);
1033  return -stanza_err_BAD_REQUEST;
1034  }
1035 
1036  log_debug(ZONE, "s10n item with value '%.*s' (to %d from %d)", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value), zitem->to, zitem->from);
1037  }
1038  }
1039 
1040  /* action */
1041  if(NAD_AVAL_L(pkt->nad, action) == 4 && strncmp("deny", NAD_AVAL(pkt->nad, action), 4) == 0) {
1042  zitem->deny = 1;
1043  log_debug(ZONE, "deny rule");
1044  } else if(NAD_AVAL_L(pkt->nad, action) == 5 && strncmp("allow", NAD_AVAL(pkt->nad, action), 5) == 0) {
1045  zitem->deny = 0;
1046  log_debug(ZONE, "allow rule");
1047  } else {
1048  log_debug(ZONE, "unknown action '%.*s', failing request", NAD_AVAL_L(pkt->nad, action), NAD_AVAL(pkt->nad, action));
1049  pool_free(p);
1050  os_free(os);
1051  return -stanza_err_BAD_REQUEST;
1052  }
1053 
1054  os_object_put(o, "deny", &zitem->deny, os_type_BOOLEAN);
1055 
1056  /* order */
1057  snprintf(corder, 14, "%.*s", NAD_AVAL_L(pkt->nad, order), NAD_AVAL(pkt->nad, order));
1058  corder[13] = '\0';
1059  zitem->order = atoi(corder);
1060 
1061  os_object_put(o, "order", &zitem->order, os_type_INTEGER);
1062 
1063  /* block types */
1064  if(nad_find_elem(pkt->nad, item, ns, "message", 1) >= 0)
1065  zitem->block |= block_MESSAGE;
1066  if(nad_find_elem(pkt->nad, item, ns, "presence-in", 1) >= 0)
1067  zitem->block |= block_PRES_IN;
1068  if(nad_find_elem(pkt->nad, item, ns, "presence-out", 1) >= 0)
1069  zitem->block |= block_PRES_OUT;
1070  if(nad_find_elem(pkt->nad, item, ns, "iq", 1) >= 0)
1071  zitem->block |= block_IQ;
1072 
1073  /* merge block all */
1074  if(zitem->block & block_MESSAGE &&
1075  zitem->block & block_PRES_IN &&
1076  zitem->block & block_PRES_OUT &&
1077  zitem->block & block_IQ)
1078  zitem->block = block_NONE;
1079 
1080  os_object_put(o, "block", &zitem->block, os_type_INTEGER);
1081 
1082  /* insert it */
1083  for(scan = zlist->items; scan != NULL; scan = scan->next)
1084  if(zitem->order < scan->order)
1085  break;
1086 
1087  /* we're >= everyone, add us to the end */
1088  if(scan == NULL) {
1089  if(zlist->last == NULL)
1090  zlist->items = zlist->last = zitem;
1091  else {
1092  zlist->last->next = zitem;
1093  zitem->prev = zlist->last;
1094  zlist->last = zitem;
1095  }
1096  }
1097 
1098  /* insert just before scan */
1099  else {
1100  if(zlist->items == scan) {
1101  zitem->next = zlist->items;
1102  zlist->items = zitem;
1103  scan->prev = zitem;
1104  } else {
1105  zitem->next = scan;
1106  zitem->prev = scan->prev;
1107  scan->prev->next = zitem;
1108  scan->prev = zitem;
1109  }
1110  }
1111 
1112  /* next item */
1113  item = nad_find_elem(pkt->nad, item, ns, "item", 0);
1114  }
1115 
1116  /* write the whole list out */
1117  sprintf(filter, "(list=%zu:%s)", strlen(zlist->name), zlist->name);
1118 
1119  ret = storage_replace(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), filter, os);
1120  os_free(os);
1121 
1122  /* failed! */
1123  if(ret != st_SUCCESS) {
1124  pool_free(zlist->p);
1126  }
1127 
1128  /* old list pointer */
1129  old = xhash_get(z->lists, zlist->name);
1130 
1131  /* removed list */
1132  if(zlist->items == NULL) {
1133  log_debug(ZONE, "removed list %s", zlist->name);
1134  xhash_zap(z->lists, zlist->name);
1135  pool_free(zlist->p);
1136  if(old != NULL) pool_free(old->p);
1137  zlist = NULL;
1138  } else {
1139  log_debug(ZONE, "updated list %s", zlist->name);
1140  xhash_put(z->lists, zlist->name, (void *) zlist);
1141  if(old != NULL) pool_free(old->p);
1142  }
1143 
1144  /* if this was a new list, then noone has it active yet */
1145  if(old != NULL) {
1146 
1147  /* relink */
1148  log_debug(ZONE, "relinking sessions");
1149 
1150  /* loop through sessions, relink */
1151  for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next)
1152  if(sscan->module_data[mod->index] != NULL && ((privacy_t) sscan->module_data[mod->index])->active == old) {
1153  ((privacy_t) sscan->module_data[mod->index])->active = zlist;
1154  log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sscan->jid), (zlist != NULL) ? zlist->name : "(NONE)");
1155  }
1156 
1157  /* default list */
1158  if(z->def == old) {
1159  z->def = zlist;
1160 
1161  if(zlist == NULL) {
1162  storage_delete(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL);
1163  log_debug(ZONE, "removed default list");
1164  }
1165 
1166  else {
1167  os = os_new();
1168  o = os_object_new(os);
1169 
1170  os_object_put(o, "default", zlist->name, os_type_STRING);
1171 
1172  storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os);
1173 
1174  os_free(os);
1175 
1176  log_debug(ZONE, "default list is now '%s'", (zlist != NULL) ? zlist->name : "(NONE)");
1177  }
1178  }
1179  }
1180  }
1181 
1182  /* set the active list */
1183  if(active >= 0) {
1184  name = nad_find_attr(pkt->nad, active, -1, "name", NULL);
1185  if(name < 0) {
1186  /* no name, no active list */
1187  log_debug(ZONE, "clearing active list for session '%s'", jid_full(sess->jid));
1188  ((privacy_t) sess->module_data[mod->index])->active = NULL;
1189  }
1190 
1191  else {
1192  snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name));
1193  str[255] = '\0';
1194 
1195  zlist = xhash_get(z->lists, str);
1196  if(zlist == NULL) {
1197  log_debug(ZONE, "request to make list '%s' active, but there's no such list", str);
1198  return -stanza_err_ITEM_NOT_FOUND;
1199  }
1200 
1201  ((privacy_t) sess->module_data[mod->index])->active = zlist;
1202 
1203  log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sess->jid), str);
1204  }
1205  }
1206 
1207  /* set the default list */
1208  if(def >= 0) {
1209  name = nad_find_attr(pkt->nad, def, -1, "name", NULL);
1210  if(name < 0) {
1211  /* no name, no default list */
1212  log_debug(ZONE, "clearing default list for '%s'", jid_user(sess->user->jid));
1213  z->def = NULL;
1214  }
1215 
1216  else {
1217  snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name));
1218  str[255] = '\0';
1219 
1220  zlist = xhash_get(z->lists, str);
1221  if(zlist == NULL) {
1222  log_debug(ZONE, "request to make list '%s' default, but there's no such list");
1223  return -stanza_err_ITEM_NOT_FOUND;
1224  }
1225 
1226  z->def = zlist;
1227 
1228  os = os_new();
1229  o = os_object_new(os);
1230 
1231  os_object_put(o, "default", zlist->name, os_type_STRING);
1232 
1233  storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os);
1234 
1235  os_free(os);
1236 
1237  log_debug(ZONE, "'%s' now has default list '%s'", jid_user(sess->user->jid), str);
1238  }
1239  }
1240 
1241  /* done, let them know */
1242  result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
1243 
1244  pkt_id(pkt, result);
1245 
1246  /* done with this */
1247  pkt_free(pkt);
1248 
1249  /* give it to the session */
1250  pkt_sess(result, sess);
1251 
1252  /* all done */
1253  return mod_HANDLED;
1254  }
1255 
1256  /* its a get */
1257 
1258  /* only allowed to request one list, if any */
1259  list = nad_find_elem(pkt->nad, query, ns, "list", 1);
1260  if(list >= 0 && nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0)
1261  return -stanza_err_BAD_REQUEST;
1262 
1263  result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
1264 
1265  pkt_id(pkt, result);
1266 
1267  ns = nad_add_namespace(result->nad, uri_PRIVACY, NULL);
1268  query = nad_insert_elem(result->nad, 1, ns, "query", NULL);
1269 
1270  /* just do one */
1271  if(list >= 0) {
1272  name = nad_find_attr(pkt->nad, list, -1, "name", NULL);
1273 
1274  zlist = xhash_getx(z->lists, NAD_AVAL(pkt->nad, name), NAD_AVAL_L(pkt->nad, name));
1275  if(zlist == NULL)
1276  return -stanza_err_ITEM_NOT_FOUND;
1277 
1278  _privacy_result_builder(z->lists, zlist->name, (void *) zlist, (void *) result);
1279  }
1280 
1281  else {
1282  /* walk the list hash and add the lists in */
1283  xhash_walk(z->lists, _privacy_lists_result_builder, (void *) result);
1284  }
1285 
1286  /* tell them about current active and default list if they asked for everything */
1287  if(list < 0) {
1288  /* active */
1289  if(((privacy_t) sess->module_data[mod->index])->active != NULL) {
1290  active = nad_insert_elem(result->nad, query, ns, "active", NULL);
1291  nad_set_attr(result->nad, active, -1, "name", ((privacy_t) sess->module_data[mod->index])->active->name, 0);
1292  }
1293 
1294  /* and the default list */
1295  if(z->def != NULL) {
1296  def = nad_insert_elem(result->nad, query, ns, "default", NULL);
1297  nad_set_attr(result->nad, def, -1, "name", z->def->name, 0);
1298  }
1299  }
1300 
1301  /* give it to the session */
1302  pkt_sess(result, sess);
1303 
1304  /* done with this */
1305  pkt_free(pkt);
1306 
1307  /* all done */
1308  return mod_HANDLED;
1309 }
1310 
1312  log_debug(ZONE, "deleting privacy data for %s", jid_user(jid));
1313 
1314  storage_delete(mi->sm->st, "privacy-items", jid_user(jid), NULL);
1315  storage_delete(mi->sm->st, "privacy-default", jid_user(jid), NULL);
1316 }
1317 
1318 static void _privacy_free(module_t mod) {
1321 }
1322 
1323 DLLEXPORT int module_init(mod_instance_t mi, const char *arg) {
1324  module_t mod = mi->mod;
1325 
1326  if (mod->init) return 0;
1327 
1331  mod->in_sess = _privacy_in_sess;
1333  mod->free = _privacy_free;
1334 
1339 
1340  return 0;
1341 }
pkt_t pkt_error(pkt_t pkt, int err)
Definition: pkt.c:30
user_t user
user this session belongs to
Definition: sm.h:256
char * group
Definition: mod_privacy.c:72
xht roster
roster for this user (key is full jid of item, value is item_t)
Definition: sm.h:241
pkt_type_t type
packet type
Definition: sm.h:138
int sm_register_ns(sm_t sm, const char *uri)
register a new global ns
Definition: sm.c:324
jid_t jid
session jid (user@host/res)
Definition: sm.h:258
void pool_free(pool_t p)
Definition: pool.c:226
data structures and prototypes for the session manager
int nad_insert_elem(nad_t nad, int parent, int ns, const char *name, const char *cdata)
shove in a new child elem after the given one
Definition: nad.c:405
pkt_t pres
copy of the last presence packet we received
Definition: sm.h:265
void sm_unregister_ns(sm_t sm, const char *uri)
unregister a global ns
Definition: sm.c:338
zebra_item_type_t
Definition: mod_privacy.c:37
void xhash_free(xht h)
Definition: xhash.c:241
mod_ret_t(* out_router)(mod_instance_t mi, pkt_t pkt)
out-router handler
Definition: sm.h:427
const char * jid_user(jid_t jid)
expand and return the user
Definition: jid.c:339
struct zebra_item_st * zebra_item_t
Definition: mod_privacy.c:35
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:347
jid_t jid_new(const char *id, int len)
make a new jid
Definition: jid.c:81
single instance of a module in a chain
Definition: sm.h:446
zebra_item_type_t type
Definition: mod_privacy.c:68
int nad_find_elem(nad_t nad, int elem, int ns, const char *name, int depth)
locate the next elem at a given depth with an optional matching name
Definition: nad.c:204
void * xhash_getx(xht h, const char *key, int len)
Definition: xhash.c:170
static void _privacy_lists_result_builder(const char *name, int namelen, void *val, void *arg)
add a list to the return packet
Definition: mod_privacy.c:593
int init
number of times the module intialiser has been called
Definition: sm.h:416
zebra_item_t prev
Definition: mod_privacy.c:83
jid_t A
list of jids that this session has sent directed presence to
Definition: sm.h:271
static mod_ret_t _privacy_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt)
list management requests
Definition: mod_privacy.c:658
zebra_list_t active
Definition: mod_privacy.c:88
info/query (set)
Definition: sm.h:107
void ** module_data
per-session module data
Definition: sm.h:274
#define stanza_err_FEATURE_NOT_IMPLEMENTED
Definition: util.h:369
int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
bring a new namespace into scope
Definition: nad.c:734
sm_t sm
sm context
Definition: sm.h:237
pkt_t pkt_dup(pkt_t pkt, const char *to, const char *from)
duplicate pkt, replacing addresses
Definition: pkt.c:84
SM_API user_t user_load(sm_t sm, jid_t jid)
fetch user data
Definition: user.c:52
mod_ret_t(* in_router)(mod_instance_t mi, pkt_t pkt)
in-router handler
Definition: sm.h:424
zebra_block_type_t
Definition: mod_privacy.c:44
sm_t sm
sm context
Definition: sm.h:130
void pkt_id_new(pkt_t pkt)
create an id value for new iq packets
Definition: pkt.c:364
char * resource
Definition: jid.h:46
static void _privacy_user_free(zebra_t *z)
Definition: mod_privacy.c:118
int xhash_iter_next(xht h)
Definition: xhash.c:320
#define pool_new()
Definition: pool.h:97
int pres_trust(user_t user, jid_t jid)
see if the jid is trusted (ie in the roster with s10n="from" or "both")
Definition: pres.c:337
zebra_list_t def
Definition: mod_privacy.c:56
int index
module index.
Definition: sm.h:408
static mod_ret_t _privacy_in_router(mod_instance_t mi, pkt_t pkt)
check incoming packets
Definition: mod_privacy.c:405
pool_t p
memory pool this session is allocated off
Definition: sm.h:254
mm_t mm
module manager
Definition: sm.h:404
zebra_item_t last
Definition: mod_privacy.c:64
xht lists
Definition: mod_privacy.c:54
static void _privacy_result_builder(xht zhash, const char *name, void *val, void *arg)
add a list to the return packet
Definition: mod_privacy.c:525
#define urn_BLOCKING_ERR
Definition: uri.h:76
#define DLLEXPORT
Definition: c2s.h:47
sess_t next
next session (in a list of sessions)
Definition: sm.h:276
void nad_set_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen)
create, update, or zap any matching attr on this elem
Definition: nad.c:375
zebra_item_t items
Definition: mod_privacy.c:64
sess_t top
top priority session
Definition: sm.h:244
void pool_cleanup(pool_t p, pool_cleanup_t f, void *arg)
public cleanup utils, insert in a way that they are run FIFO, before mem frees
Definition: pool.c:251
sm_t sm
sm context
Definition: sm.h:366
mod_ret_t(* in_sess)(mod_instance_t mi, sess_t sess, pkt_t pkt)
in-sess handler
Definition: sm.h:423
pool_t p
memory pool this user is allocated off
Definition: sm.h:235
sess_t sessions
list of action sessions
Definition: sm.h:243
module_t mod
module that this is an instance of
Definition: sm.h:449
jid_t from
packet addressing (not used for routing)
Definition: sm.h:140
pkt_type_t
packet types
Definition: sm.h:93
void feature_unregister(sm_t sm, const char *feature)
unregister feature
Definition: feature.c:45
void ** val
Definition: c2s.h:401
packet summary data wrapper
Definition: sm.h:129
void * pmalloco(pool_t p, int size)
easy safety utility (for creating blank mem for structs, etc)
Definition: pool.c:183
int jid_search(jid_t list, jid_t jid)
util to search through jids
Definition: jid.c:413
char * pstrdupx(pool_t p, const char *src, int len)
use given size
Definition: pool.c:205
storage_t st
storage subsystem
Definition: sm.h:211
nad_t nad
nad of the entire packet
Definition: sm.h:146
zebra_list_t * z_val
Definition: mod_privacy.c:98
void jid_free(jid_t jid)
free a jid
Definition: jid.c:286
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
static mod_ret_t _privacy_out_router(mod_instance_t mi, pkt_t pkt)
check outgoing packets
Definition: mod_privacy.c:463
zebra data for a single user
Definition: mod_privacy.c:53
#define stanza_err_BAD_REQUEST
Definition: util.h:367
int ngroups
number of groups in groups array
Definition: sm.h:157
char * domain
Definition: jid.h:45
#define uri_PRIVACY
Definition: uri.h:74
Definition: jid.h:42
struct pkt_st * pkt_t
packet summary data wrapper
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
Definition: xhash.c:374
const char ** groups
groups this item is in
Definition: sm.h:155
#define NAD_AVAL_L(N, A)
Definition: nad.h:190
void pkt_id(pkt_t src, pkt_t dest)
convenience - copy the packet id from src to dest
Definition: pkt.c:353
int jid_compare_full(jid_t a, jid_t b)
compare two full jids
Definition: jid.c:364
void pkt_router(pkt_t pkt)
Definition: pkt.c:379
void xhash_zap(xht h, const char *key)
Definition: xhash.c:235
static void _unblock_jid(user_t user, storage_t st, zebra_list_t zlist, jid_t jid)
remove jid deny ocurrences from the privacy list, unblock all if no jid given to match, then update unblocked contact with presence information
Definition: mod_privacy.c:608
void pkt_free(pkt_t pkt)
Definition: pkt.c:315
#define log_debug(...)
Definition: log.h:65
roster items
Definition: sm.h:150
void feature_register(sm_t sm, const char *feature)
register a feature
Definition: feature.c:37
info/query (get)
Definition: sm.h:106
zebra_block_type_t block
Definition: mod_privacy.c:81
sess_t sess_match(user_t user, const char *resource)
match a session by resource
Definition: sess.c:206
#define NAD_AVAL(N, A)
Definition: nad.h:189
static void _privacy_free_z(zebra_t z)
Definition: mod_privacy.c:101
presence
Definition: sm.h:99
packet was unhandled, should be passed to the next module
Definition: sm.h:340
int ns
iq sub-namespace
Definition: sm.h:142
#define stanza_err_ITEM_NOT_FOUND
Definition: util.h:373
packet was handled (and freed)
Definition: sm.h:339
There is one instance of this struct per user who is logged in to this c2s instance.
Definition: c2s.h:74
int(* user_load)(mod_instance_t mi, user_t user)
user-load handler
Definition: sm.h:434
struct privacy_st * privacy_t
int xhash_iter_first(xht h)
iteration
Definition: xhash.c:311
void xhash_walk(xht h, xhash_walker w, void *arg)
Definition: xhash.c:268
struct zebra_st * zebra_t
Definition: mod_privacy.c:33
void(* user_delete)(mod_instance_t mi, jid_t jid)
user-delete handler
Definition: sm.h:438
int available
true if this session is available
Definition: sm.h:267
message
Definition: sm.h:95
jid_t to
Definition: sm.h:140
int from
subscription to this item (they get presence FROM us, they send presence TO us)
Definition: sm.h:159
int to
Definition: sm.h:159
char * pstrdup(pool_t p, const char *src)
XXX efficient: move this to const char * and then loop throug the existing heaps to see if src is wit...
Definition: pool.c:191
#define stanza_err_NOT_ACCEPTABLE
Definition: util.h:375
jid_t jid
user jid (user@host)
Definition: sm.h:239
void * xhash_get(xht h, const char *key)
Definition: xhash.c:184
#define urn_BLOCKING
Definition: uri.h:75
static int ns_BLOCKING
Definition: mod_privacy.c:31
static int _privacy_action(user_t user, zebra_list_t zlist, jid_t jid, pkt_type_t ptype, int in)
returns 0 if the packet should be allowed, otherwise 1
Definition: mod_privacy.c:319
#define ZONE
Definition: mio_impl.h:76
static int _privacy_user_load(mod_instance_t mi, user_t user)
Definition: mod_privacy.c:123
session packet handling
Definition: c2s.h:399
struct zebra_list_st * zebra_list_t
Definition: mod_privacy.c:34
jid_t E
list of jids that bounced presence updates we sent them
Definition: sm.h:272
void(* free)(module_t mod)
called when module is freed
Definition: sm.h:442
xht xhash_new(int prime)
Definition: xhash.c:96
data for a single module
Definition: sm.h:403
zebra_item_t next
Definition: mod_privacy.c:83
int nad_find_attr(nad_t nad, int elem, int ns, const char *name, const char *val)
get a matching attr on this elem, both name and optional val
Definition: nad.c:235
void ** module_data
per-user module data
Definition: sm.h:249
presence (probe)
Definition: sm.h:101
pool - base node for a pool.
Definition: pool.h:80
pkt_t pkt_create(sm_t sm, const char *elem, const char *type, const char *to, const char *from)
Definition: pkt.c:328
static void _privacy_free(module_t mod)
Definition: mod_privacy.c:1318
mod_ret_t
module return values
Definition: sm.h:338
static int ns_PRIVACY
Definition: mod_privacy.c:30
sm_t sm
sm context
Definition: sm.h:447
static void _privacy_user_delete(mod_instance_t mi, jid_t jid)
Definition: mod_privacy.c:1311
#define stanza_err_INTERNAL_SERVER_ERROR
Definition: util.h:372
void pkt_sess(pkt_t pkt, sess_t sess)
Definition: pkt.c:459
int blocklist
Definition: mod_privacy.c:91
char * node
Definition: jid.h:44
DLLEXPORT int module_init(mod_instance_t mi, const char *arg)
Definition: mod_privacy.c:1323
data for a single user
Definition: sm.h:234
int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix)
find a namespace in scope
Definition: nad.c:290