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
23 /** @file sm/mod_privacy.c
24 * @brief XEP-0016 Privacy Lists and XEP-0191 Simple Comunications Blocking
25 * @author Robert Norris
26 * $Date: 2005/08/17 07:48:28 $
27 * $Revision: 1.32 $
28 */
29
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 {
38 zebra_NONE,
39 zebra_JID,
40 zebra_GROUP,
41 zebra_S10N
42 } zebra_item_type_t;
43
44 typedef enum {
45 block_NONE = 0x00,
46 block_MESSAGE = 0x01,
47 block_PRES_IN = 0x02,
48 block_PRES_OUT = 0x04,
49 block_IQ = 0x08
50 } zebra_block_type_t;
51
52 /** zebra data for a single user */
53 struct zebra_st {
54 xht lists;
55
56 zebra_list_t def;
57 };
58
59 struct zebra_list_st {
60 pool_t p;
61
62 char *name;
63
64 zebra_item_t items, last;
65 };
66
67 struct zebra_item_st {
68 zebra_item_type_t type;
69
70 jid_t jid;
71
72 char *group;
73
74 int to;
75 int from;
76
77 int deny; /* 0 = allow, 1 = deny */
78
79 int order;
80
81 zebra_block_type_t block;
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
_privacy_free_z(zebra_t z)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
_privacy_user_free(zebra_t * z)118 static void _privacy_user_free(zebra_t *z) {
119 if(*z != NULL)
120 _privacy_free_z(*z);
121 }
122
_privacy_user_load(mod_instance_t mi,user_t user)123 static int _privacy_user_load(mod_instance_t mi, user_t user) {
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
318 /** returns 0 if the packet should be allowed, otherwise 1 */
_privacy_action(user_t user,zebra_list_t zlist,jid_t jid,pkt_type_t ptype,int in)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
404 /** check incoming packets */
_privacy_in_router(mod_instance_t mi,pkt_t pkt)405 static mod_ret_t _privacy_in_router(mod_instance_t mi, pkt_t pkt) {
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)
455 return -stanza_err_FEATURE_NOT_IMPLEMENTED;
456
457 /* drop it */
458 pkt_free(pkt);
459 return mod_HANDLED;
460 }
461
462 /** check outgoing packets */
_privacy_out_router(mod_instance_t mi,pkt_t pkt)463 static mod_ret_t _privacy_out_router(mod_instance_t mi, pkt_t pkt) {
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 */
511 pkt_error(pkt, stanza_err_NOT_ACCEPTABLE);
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
524 /** add a list to the return packet */
_privacy_result_builder(xht zhash,const char * name,void * val,void * arg)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
592 /** add a list to the return packet */
_privacy_lists_result_builder(const char * name,int namelen,void * val,void * arg)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
605 /** remove jid deny ocurrences from the privacy list,
606 unblock all if no jid given to match,
607 then update unblocked contact with presence information */
_unblock_jid(user_t user,storage_t st,zebra_list_t zlist,jid_t jid)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
657 /** list management requests */
_privacy_in_sess(mod_instance_t mi,sess_t sess,pkt_t pkt)658 static mod_ret_t _privacy_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
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)
732 return -stanza_err_INTERNAL_SERVER_ERROR;
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);
822 return -stanza_err_INTERNAL_SERVER_ERROR;
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);
838 return -stanza_err_ITEM_NOT_FOUND;
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 result->from = NULL;
865 }
866 pkt_id_new(result);
867 pkt_sess(result, sscan);
868 }
869 }
870
871 /* and done with request */
872 pkt_free(pkt);
873 return mod_HANDLED;
874 }
875
876 /* it's a get */
877 ns = nad_find_scoped_namespace(pkt->nad, urn_BLOCKING, NULL);
878 blocking = nad_find_elem(pkt->nad, 1, ns, "blocklist", 1);
879 if(blocking < 0)
880 return -stanza_err_BAD_REQUEST;
881
882 result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
883 pkt_id(pkt, result);
884 ns = nad_add_namespace(result->nad, urn_BLOCKING, NULL);
885 blocking = nad_insert_elem(result->nad, 1, ns, "blocklist", NULL);
886
887 /* insert items only from the default list */
888 if(z->def != NULL) {
889 log_debug(ZONE, "blocking list is '%s'", z->def->name);
890 zlist = xhash_get(z->lists, z->def->name);
891 /* run through the items and build the nad */
892 for(zitem = zlist->items; zitem != NULL; zitem = zitem->next) {
893 /* we're interested in items type 'jid' with action 'deny' only */
894 if(zitem->type == zebra_JID && zitem->deny) {
895 item = nad_insert_elem(result->nad, blocking, -1, "item", NULL);
896 nad_set_attr(result->nad, item, -1, "jid", jid_full(zitem->jid), 0);
897 }
898 }
899
900 /* mark that the blocklist was requested */
901 ((privacy_t) sess->module_data[mod->index])->blocklist = 1;
902 }
903
904 /* give it to the session */
905 pkt_sess(result, sess);
906 pkt_free(pkt);
907 return mod_HANDLED;
908 }
909
910 /* else handle XEP-0016: Privacy Lists */
911
912 /* find the query */
913 ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL);
914 query = nad_find_elem(pkt->nad, 1, ns, "query", 1);
915 if(query < 0)
916 return -stanza_err_BAD_REQUEST;
917
918 /* update lists or set the active list */
919 if(pkt->type == pkt_IQ_SET) {
920 /* find out what we're doing */
921 list = nad_find_elem(pkt->nad, query, ns, "list", 1);
922 active = nad_find_elem(pkt->nad, query, ns, "active", 1);
923 def = nad_find_elem(pkt->nad, query, ns, "default", 1);
924
925 /* we need something to do, but we can't do it all at once */
926 if((list < 0 && active < 0 && def < 0) || (list >= 0 && (active >=0 || def >= 0)))
927 return -stanza_err_BAD_REQUEST;
928
929 /* loop over any/all lists and store them */
930 if(list >= 0) {
931 /* only allowed to change one list at a time */
932 if(nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0)
933 return -stanza_err_BAD_REQUEST;
934
935 /* get the list name */
936 name = nad_find_attr(pkt->nad, list, -1, "name", NULL);
937 if(name < 0) {
938 log_debug(ZONE, "no list name specified, failing request");
939 return -stanza_err_BAD_REQUEST;
940 }
941
942 snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name));
943 str[255] = '\0';
944
945 log_debug(ZONE, "updating list %s", str);
946
947 /* make a new one */
948 p = pool_new();
949
950 zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st));
951
952 zlist->p = p;
953 zlist->name = pstrdup(p, str);
954
955 os = os_new();
956
957 /* loop over the items */
958 item = nad_find_elem(pkt->nad, list, ns, "item", 1);
959 while(item >= 0) {
960 /* extract things */
961 type = nad_find_attr(pkt->nad, item, -1, "type", 0);
962 value = nad_find_attr(pkt->nad, item, -1, "value", 0);
963 action = nad_find_attr(pkt->nad, item, -1, "action", 0);
964 order = nad_find_attr(pkt->nad, item, -1, "order", 0);
965
966 /* sanity */
967 if(action < 0 || order < 0 || (type >= 0 && value < 0)) {
968 pool_free(p);
969 os_free(os);
970 return -stanza_err_BAD_REQUEST;
971 }
972
973 /* new item */
974 zitem = (zebra_item_t) pmalloco(p, sizeof(struct zebra_item_st));
975
976 /* have to store it too */
977 o = os_object_new(os);
978 os_object_put(o, "list", zlist->name, os_type_STRING);
979
980 /* type & value */
981 if(type >= 0) {
982 if(NAD_AVAL_L(pkt->nad, type) == 3 && strncmp("jid", NAD_AVAL(pkt->nad, type), 3) == 0) {
983 zitem->type = zebra_JID;
984
985 zitem->jid = jid_new(NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value));
986 if(zitem->jid == NULL) {
987 log_debug(ZONE, "invalid jid '%.*s', failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value));
988 pool_free(p);
989 os_free(os);
990 return -stanza_err_BAD_REQUEST;
991 }
992
993 pool_cleanup(p, (void *) jid_free, zitem->jid);
994
995 log_debug(ZONE, "jid item with value '%s'", jid_full(zitem->jid));
996
997 os_object_put(o, "type", "jid", os_type_STRING);
998 os_object_put(o, "value", jid_full(zitem->jid), os_type_STRING);
999 }
1000
1001 else if(NAD_AVAL_L(pkt->nad, type) == 5 && strncmp("group", NAD_AVAL(pkt->nad, type), 5) == 0) {
1002 zitem->type = zebra_GROUP;
1003
1004 zitem->group = pstrdupx(zlist->p, NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value));
1005
1006 /* !!! check if the group exists */
1007
1008 log_debug(ZONE, "group item with value '%s'", zitem->group);
1009
1010 os_object_put(o, "type", "group", os_type_STRING);
1011 os_object_put(o, "value", zitem->group, os_type_STRING);
1012 }
1013
1014 else if(NAD_AVAL_L(pkt->nad, type) == 12 && strncmp("subscription", NAD_AVAL(pkt->nad, type), 12) == 0) {
1015 zitem->type = zebra_S10N;
1016
1017 os_object_put(o, "type", "subscription", os_type_STRING);
1018
1019 if(NAD_AVAL_L(pkt->nad, value) == 2 && strncmp("to", NAD_AVAL(pkt->nad, value), 2) == 0) {
1020 zitem->to = 1;
1021 os_object_put(o, "value", "to", os_type_STRING);
1022 } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("from", NAD_AVAL(pkt->nad, value), 4) == 0) {
1023 zitem->from = 1;
1024 os_object_put(o, "value", "from", os_type_STRING);
1025 } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("both", NAD_AVAL(pkt->nad, value), 4) == 0) {
1026 zitem->to = zitem->from = 1;
1027 os_object_put(o, "value", "both", os_type_STRING);
1028 } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("none", NAD_AVAL(pkt->nad, value), 4) == 0)
1029 os_object_put(o, "value", "none", os_type_STRING);
1030 else {
1031 log_debug(ZONE, "invalid value '%.*s' on s10n item, failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value));
1032 pool_free(p);
1033 os_free(os);
1034 return -stanza_err_BAD_REQUEST;
1035 }
1036
1037 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);
1038 }
1039 }
1040
1041 /* action */
1042 if(NAD_AVAL_L(pkt->nad, action) == 4 && strncmp("deny", NAD_AVAL(pkt->nad, action), 4) == 0) {
1043 zitem->deny = 1;
1044 log_debug(ZONE, "deny rule");
1045 } else if(NAD_AVAL_L(pkt->nad, action) == 5 && strncmp("allow", NAD_AVAL(pkt->nad, action), 5) == 0) {
1046 zitem->deny = 0;
1047 log_debug(ZONE, "allow rule");
1048 } else {
1049 log_debug(ZONE, "unknown action '%.*s', failing request", NAD_AVAL_L(pkt->nad, action), NAD_AVAL(pkt->nad, action));
1050 pool_free(p);
1051 os_free(os);
1052 return -stanza_err_BAD_REQUEST;
1053 }
1054
1055 os_object_put(o, "deny", &zitem->deny, os_type_BOOLEAN);
1056
1057 /* order */
1058 snprintf(corder, 14, "%.*s", NAD_AVAL_L(pkt->nad, order), NAD_AVAL(pkt->nad, order));
1059 corder[13] = '\0';
1060 zitem->order = atoi(corder);
1061
1062 os_object_put(o, "order", &zitem->order, os_type_INTEGER);
1063
1064 /* block types */
1065 if(nad_find_elem(pkt->nad, item, ns, "message", 1) >= 0)
1066 zitem->block |= block_MESSAGE;
1067 if(nad_find_elem(pkt->nad, item, ns, "presence-in", 1) >= 0)
1068 zitem->block |= block_PRES_IN;
1069 if(nad_find_elem(pkt->nad, item, ns, "presence-out", 1) >= 0)
1070 zitem->block |= block_PRES_OUT;
1071 if(nad_find_elem(pkt->nad, item, ns, "iq", 1) >= 0)
1072 zitem->block |= block_IQ;
1073
1074 /* merge block all */
1075 if(zitem->block & block_MESSAGE &&
1076 zitem->block & block_PRES_IN &&
1077 zitem->block & block_PRES_OUT &&
1078 zitem->block & block_IQ)
1079 zitem->block = block_NONE;
1080
1081 os_object_put(o, "block", &zitem->block, os_type_INTEGER);
1082
1083 /* insert it */
1084 for(scan = zlist->items; scan != NULL; scan = scan->next)
1085 if(zitem->order < scan->order)
1086 break;
1087
1088 /* we're >= everyone, add us to the end */
1089 if(scan == NULL) {
1090 if(zlist->last == NULL)
1091 zlist->items = zlist->last = zitem;
1092 else {
1093 zlist->last->next = zitem;
1094 zitem->prev = zlist->last;
1095 zlist->last = zitem;
1096 }
1097 }
1098
1099 /* insert just before scan */
1100 else {
1101 if(zlist->items == scan) {
1102 zitem->next = zlist->items;
1103 zlist->items = zitem;
1104 scan->prev = zitem;
1105 } else {
1106 zitem->next = scan;
1107 zitem->prev = scan->prev;
1108 scan->prev->next = zitem;
1109 scan->prev = zitem;
1110 }
1111 }
1112
1113 /* next item */
1114 item = nad_find_elem(pkt->nad, item, ns, "item", 0);
1115 }
1116
1117 /* write the whole list out */
1118 sprintf(filter, "(list=%zu:%s)", strlen(zlist->name), zlist->name);
1119
1120 ret = storage_replace(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), filter, os);
1121 os_free(os);
1122
1123 /* failed! */
1124 if(ret != st_SUCCESS) {
1125 pool_free(zlist->p);
1126 return -stanza_err_INTERNAL_SERVER_ERROR;
1127 }
1128
1129 /* old list pointer */
1130 old = xhash_get(z->lists, zlist->name);
1131
1132 /* removed list */
1133 if(zlist->items == NULL) {
1134 log_debug(ZONE, "removed list %s", zlist->name);
1135 xhash_zap(z->lists, zlist->name);
1136 pool_free(zlist->p);
1137 if(old != NULL) pool_free(old->p);
1138 zlist = NULL;
1139 } else {
1140 log_debug(ZONE, "updated list %s", zlist->name);
1141 xhash_put(z->lists, zlist->name, (void *) zlist);
1142 if(old != NULL) pool_free(old->p);
1143 }
1144
1145 /* if this was a new list, then noone has it active yet */
1146 if(old != NULL) {
1147
1148 /* relink */
1149 log_debug(ZONE, "relinking sessions");
1150
1151 /* loop through sessions, relink */
1152 for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next)
1153 if(sscan->module_data[mod->index] != NULL && ((privacy_t) sscan->module_data[mod->index])->active == old) {
1154 ((privacy_t) sscan->module_data[mod->index])->active = zlist;
1155 log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sscan->jid), (zlist != NULL) ? zlist->name : "(NONE)");
1156 }
1157
1158 /* default list */
1159 if(z->def == old) {
1160 z->def = zlist;
1161
1162 if(zlist == NULL) {
1163 storage_delete(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL);
1164 log_debug(ZONE, "removed default list");
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->name);
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 else {
1191 snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name));
1192 str[255] = '\0';
1193
1194 zlist = xhash_get(z->lists, str);
1195 if(zlist == NULL) {
1196 log_debug(ZONE, "request to make list '%s' active, but there's no such list", str);
1197 return -stanza_err_ITEM_NOT_FOUND;
1198 }
1199
1200 ((privacy_t) sess->module_data[mod->index])->active = zlist;
1201
1202 log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sess->jid), str);
1203 }
1204 }
1205
1206 /* set the default list */
1207 if(def >= 0) {
1208 name = nad_find_attr(pkt->nad, def, -1, "name", NULL);
1209 if(name < 0) {
1210 /* no name, no default list */
1211 log_debug(ZONE, "clearing default list for '%s'", jid_user(sess->user->jid));
1212 z->def = NULL;
1213 }
1214 else {
1215 snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name));
1216 str[255] = '\0';
1217
1218 zlist = xhash_get(z->lists, str);
1219 if(zlist == NULL) {
1220 log_debug(ZONE, "request to make list '%s' default, but there's no such list");
1221 return -stanza_err_ITEM_NOT_FOUND;
1222 }
1223
1224 z->def = zlist;
1225
1226 os = os_new();
1227 o = os_object_new(os);
1228
1229 os_object_put(o, "default", zlist->name, os_type_STRING);
1230
1231 storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os);
1232
1233 os_free(os);
1234
1235 log_debug(ZONE, "'%s' now has default list '%s'", jid_user(sess->user->jid), str);
1236 }
1237 }
1238
1239 /* done, let them know */
1240 result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
1241
1242 pkt_id(pkt, result);
1243
1244 /* done with this */
1245 pkt_free(pkt);
1246
1247 /* give it to the session */
1248 pkt_sess(result, sess);
1249
1250 /* all done */
1251 return mod_HANDLED;
1252 }
1253
1254 /* its a get */
1255
1256 /* only allowed to request one list, if any */
1257 list = nad_find_elem(pkt->nad, query, ns, "list", 1);
1258 if(list >= 0 && nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0)
1259 return -stanza_err_BAD_REQUEST;
1260
1261 result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
1262
1263 pkt_id(pkt, result);
1264
1265 ns = nad_add_namespace(result->nad, uri_PRIVACY, NULL);
1266 query = nad_insert_elem(result->nad, 1, ns, "query", NULL);
1267
1268 /* just do one */
1269 if(list >= 0) {
1270 name = nad_find_attr(pkt->nad, list, -1, "name", NULL);
1271
1272 zlist = xhash_getx(z->lists, NAD_AVAL(pkt->nad, name), NAD_AVAL_L(pkt->nad, name));
1273 if(zlist == NULL)
1274 return -stanza_err_ITEM_NOT_FOUND;
1275
1276 _privacy_result_builder(z->lists, zlist->name, (void *) zlist, (void *) result);
1277 }
1278
1279 else {
1280 /* walk the list hash and add the lists in */
1281 xhash_walk(z->lists, _privacy_lists_result_builder, (void *) result);
1282 }
1283
1284 /* tell them about current active and default list if they asked for everything */
1285 if(list < 0) {
1286 /* active */
1287 if(((privacy_t) sess->module_data[mod->index])->active != NULL) {
1288 active = nad_insert_elem(result->nad, query, ns, "active", NULL);
1289 nad_set_attr(result->nad, active, -1, "name", ((privacy_t) sess->module_data[mod->index])->active->name, 0);
1290 }
1291
1292 /* and the default list */
1293 if(z->def != NULL) {
1294 def = nad_insert_elem(result->nad, query, ns, "default", NULL);
1295 nad_set_attr(result->nad, def, -1, "name", z->def->name, 0);
1296 }
1297 }
1298
1299 /* give it to the session */
1300 pkt_sess(result, sess);
1301
1302 /* done with this */
1303 pkt_free(pkt);
1304
1305 /* all done */
1306 return mod_HANDLED;
1307 }
1308
_privacy_user_delete(mod_instance_t mi,jid_t jid)1309 static void _privacy_user_delete(mod_instance_t mi, jid_t jid) {
1310 log_debug(ZONE, "deleting privacy data for %s", jid_user(jid));
1311
1312 storage_delete(mi->sm->st, "privacy-items", jid_user(jid), NULL);
1313 storage_delete(mi->sm->st, "privacy-default", jid_user(jid), NULL);
1314 }
1315
_privacy_free(module_t mod)1316 static void _privacy_free(module_t mod) {
1317 sm_unregister_ns(mod->mm->sm, uri_PRIVACY);
1318 feature_unregister(mod->mm->sm, uri_PRIVACY);
1319 }
1320
module_init(mod_instance_t mi,const char * arg)1321 DLLEXPORT int module_init(mod_instance_t mi, const char *arg) {
1322 module_t mod = mi->mod;
1323
1324 if (mod->init) return 0;
1325
1326 mod->user_load = _privacy_user_load;
1327 mod->in_router = _privacy_in_router;
1328 mod->out_router = _privacy_out_router;
1329 mod->in_sess = _privacy_in_sess;
1330 mod->user_delete = _privacy_user_delete;
1331 mod->free = _privacy_free;
1332
1333 ns_PRIVACY = sm_register_ns(mod->mm->sm, uri_PRIVACY);
1334 feature_register(mod->mm->sm, uri_PRIVACY);
1335 ns_BLOCKING = sm_register_ns(mod->mm->sm, urn_BLOCKING);
1336 feature_register(mod->mm->sm, urn_BLOCKING);
1337
1338 return 0;
1339 }
1340