jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, 00004 * Ryan Eatmon, Robert Norris 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00019 */ 00020 00021 #include "sm.h" 00022 00030 static int ns_PRIVACY = 0; 00031 static int ns_BLOCKING = 0; 00032 00033 typedef struct zebra_st *zebra_t; 00034 typedef struct zebra_list_st *zebra_list_t; 00035 typedef struct zebra_item_st *zebra_item_t; 00036 00037 typedef enum { 00038 zebra_NONE, 00039 zebra_JID, 00040 zebra_GROUP, 00041 zebra_S10N 00042 } zebra_item_type_t; 00043 00044 typedef enum { 00045 block_NONE = 0x00, 00046 block_MESSAGE = 0x01, 00047 block_PRES_IN = 0x02, 00048 block_PRES_OUT = 0x04, 00049 block_IQ = 0x08 00050 } zebra_block_type_t; 00051 00053 struct zebra_st { 00054 xht lists; 00055 00056 zebra_list_t def; 00057 }; 00058 00059 struct zebra_list_st { 00060 pool_t p; 00061 00062 char *name; 00063 00064 zebra_item_t items, last; 00065 }; 00066 00067 struct zebra_item_st { 00068 zebra_item_type_t type; 00069 00070 jid_t jid; 00071 00072 char *group; 00073 00074 int to; 00075 int from; 00076 00077 int deny; /* 0 = allow, 1 = deny */ 00078 00079 int order; 00080 00081 zebra_block_type_t block; 00082 00083 zebra_item_t next, prev; 00084 }; 00085 00086 typedef struct privacy_st { 00087 /* currently active list */ 00088 zebra_list_t active; 00089 00090 /* was blocklist requested */ 00091 int blocklist; 00092 } *privacy_t; 00093 00094 /* union for xhash_iter_get to comply with strict-alias rules for gcc3 */ 00095 union xhashv 00096 { 00097 void **val; 00098 zebra_list_t *z_val; 00099 }; 00100 00101 static void _privacy_free_z(zebra_t z) { 00102 zebra_list_t zlist; 00103 union xhashv xhv; 00104 00105 log_debug(ZONE, "freeing zebra ctx"); 00106 00107 if(xhash_iter_first(z->lists)) 00108 do { 00109 xhv.z_val = &zlist; 00110 xhash_iter_get(z->lists, NULL, NULL, xhv.val); 00111 pool_free(zlist->p); 00112 } while(xhash_iter_next(z->lists)); 00113 00114 xhash_free(z->lists); 00115 free(z); 00116 } 00117 00118 static void _privacy_user_free(zebra_t *z) { 00119 if(*z != NULL) 00120 _privacy_free_z(*z); 00121 } 00122 00123 static int _privacy_user_load(mod_instance_t mi, user_t user) { 00124 module_t mod = mi->mod; 00125 zebra_t z; 00126 os_t os; 00127 os_object_t o; 00128 zebra_list_t zlist; 00129 pool_t p; 00130 zebra_item_t zitem, scan; 00131 char *str; 00132 00133 log_debug(ZONE, "loading privacy lists for %s", jid_user(user->jid)); 00134 00135 /* free if necessary */ 00136 z = user->module_data[mod->index]; 00137 if(z != NULL) 00138 _privacy_free_z(z); 00139 00140 z = (zebra_t) calloc(1, sizeof(struct zebra_st)); 00141 00142 z->lists = xhash_new(101); 00143 00144 user->module_data[mod->index] = z; 00145 00146 pool_cleanup(user->p, (void (*))(void *) _privacy_user_free, &(user->module_data[mod->index])); 00147 00148 /* pull the whole lot */ 00149 if(storage_get(user->sm->st, "privacy-items", jid_user(user->jid), NULL, &os) == st_SUCCESS) { 00150 if(os_iter_first(os)) 00151 do { 00152 o = os_iter_object(os); 00153 00154 /* list name */ 00155 if(!os_object_get_str(os, o, "list", &str)) { 00156 log_debug(ZONE, "item with no list field, skipping"); 00157 continue; 00158 } 00159 00160 log_debug(ZONE, "got item for list %s", str); 00161 00162 zlist = xhash_get(z->lists, str); 00163 00164 /* new list */ 00165 if(zlist == NULL) { 00166 log_debug(ZONE, "creating list %s", str); 00167 00168 p = pool_new(); 00169 00170 zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st)); 00171 00172 zlist->p = p; 00173 zlist->name = pstrdup(p, str); 00174 00175 xhash_put(z->lists, zlist->name, (void *) zlist); 00176 } 00177 00178 /* new item */ 00179 zitem = (zebra_item_t) pmalloco(zlist->p, sizeof(struct zebra_item_st)); 00180 00181 /* item type */ 00182 if(os_object_get_str(os, o, "type", &str)) 00183 switch(str[0]) { 00184 case 'j': 00185 zitem->type = zebra_JID; 00186 break; 00187 00188 case 'g': 00189 zitem->type = zebra_GROUP; 00190 break; 00191 00192 case 's': 00193 zitem->type = zebra_S10N; 00194 break; 00195 } 00196 00197 /* item value, according to type */ 00198 if(zitem->type != zebra_NONE) { 00199 if(!os_object_get_str(os, o, "value", &str)) { 00200 log_debug(ZONE, "no value on non-fall-through item, dropping this item"); 00201 continue; 00202 } 00203 00204 switch(zitem->type) { 00205 00206 case zebra_JID: 00207 zitem->jid = jid_new(str, strlen(str)); 00208 if(zitem->jid == NULL) { 00209 log_debug(ZONE, "invalid jid '%s' on item, dropping this item", str); 00210 continue; 00211 } 00212 00213 pool_cleanup(zlist->p, (void *) jid_free, zitem->jid); 00214 00215 log_debug(ZONE, "jid item with value '%s'", jid_full(zitem->jid)); 00216 00217 break; 00218 00219 case zebra_GROUP: 00220 zitem->group = pstrdup(zlist->p, str); 00221 00222 log_debug(ZONE, "group item with value '%s'", zitem->group); 00223 00224 break; 00225 00226 case zebra_S10N: 00227 if(strcmp(str, "to") == 0) 00228 zitem->to = 1; 00229 else if(strcmp(str, "from") == 0) 00230 zitem->from = 1; 00231 else if(strcmp(str, "both") == 0) 00232 zitem->to = zitem->from = 1; 00233 else if(strcmp(str, "none") != 0) { 00234 log_debug(ZONE, "invalid value '%s' on s10n item, dropping this item", str); 00235 continue; 00236 } 00237 00238 log_debug(ZONE, "s10n item with value '%s' (to %d from %d)", str, zitem->to, zitem->from); 00239 00240 break; 00241 00242 case zebra_NONE: 00243 /* can't get here */ 00244 break; 00245 } 00246 } 00247 00248 /* action */ 00249 os_object_get_bool(os, o, "deny", &zitem->deny); 00250 if(zitem->deny) { 00251 log_debug(ZONE, "deny rule"); 00252 } else { 00253 log_debug(ZONE, "accept rule"); 00254 } 00255 00256 os_object_get_int(os, o, "order", &(zitem->order)); 00257 log_debug(ZONE, "order %d", zitem->order); 00258 00259 os_object_get_int(os, o, "block", (int*) &(zitem->block)); 00260 log_debug(ZONE, "block 0x%x", zitem->block); 00261 00262 /* insert it */ 00263 for(scan = zlist->items; scan != NULL; scan = scan->next) 00264 if(zitem->order < scan->order) 00265 break; 00266 00267 /* we're >= everyone, add us to the end */ 00268 if(scan == NULL) { 00269 if(zlist->last == NULL) 00270 zlist->items = zlist->last = zitem; 00271 else { 00272 zlist->last->next = zitem; 00273 zitem->prev = zlist->last; 00274 zlist->last = zitem; 00275 } 00276 } 00277 00278 /* insert just before scan */ 00279 else { 00280 if(zlist->items == scan) { 00281 zitem->next = zlist->items; 00282 zlist->items = zitem; 00283 scan->prev = zitem; 00284 } else { 00285 zitem->next = scan; 00286 zitem->prev = scan->prev; 00287 scan->prev->next = zitem; 00288 scan->prev = zitem; 00289 } 00290 } 00291 } while(os_iter_next(os)); 00292 00293 os_free(os); 00294 } 00295 00296 /* default list */ 00297 if(storage_get(user->sm->st, "privacy-default", jid_user(user->jid), NULL, &os) == st_SUCCESS) { 00298 if(os_iter_first(os)) 00299 do { 00300 o = os_iter_object(os); 00301 00302 if(os_object_get_str(os, o, "default", &str)) { 00303 z->def = (zebra_list_t) xhash_get(z->lists, str); 00304 if(z->def == NULL) { 00305 log_debug(ZONE, "storage says the default list for %s is %s, but it doesn't exist!", jid_user(user->jid), str); 00306 } else { 00307 log_debug(ZONE, "user %s has default list %s", jid_user(user->jid), str); 00308 } 00309 } 00310 } while(os_iter_next(os)); 00311 00312 os_free(os); 00313 } 00314 00315 return 0; 00316 } 00317 00319 static int _privacy_action(user_t user, zebra_list_t zlist, jid_t jid, pkt_type_t ptype, int in) { 00320 zebra_item_t scan; 00321 int match, i; 00322 item_t ritem; 00323 unsigned char domres[2048]; 00324 00325 log_debug(ZONE, "running match on list %s for %s (packet type 0x%x) (%s)", zlist->name, jid_full(jid), ptype, in ? "incoming" : "outgoing"); 00326 00327 /* loop over the list, trying to find a match */ 00328 for(scan = zlist->items; scan != NULL; scan = scan->next) { 00329 match = 0; 00330 00331 switch(scan->type) { 00332 case zebra_NONE: 00333 /* fall through, all packets match this */ 00334 match = 1; 00335 break; 00336 00337 case zebra_JID: 00338 sprintf(domres, "%s/%s", jid->domain, jid->resource); 00339 00340 /* jid check - match node@dom/res, then node@dom, then dom/resource, then dom */ 00341 if(jid_compare_full(scan->jid, jid) == 0 || 00342 strcmp(jid_full(scan->jid), jid_user(jid)) == 0 || 00343 strcmp(jid_full(scan->jid), domres) == 0 || 00344 strcmp(jid_full(scan->jid), jid->domain) == 0) 00345 match = 1; 00346 00347 break; 00348 00349 case zebra_GROUP: 00350 /* roster group check - get the roster item, node@dom/res, then node@dom, then dom */ 00351 ritem = xhash_get(user->roster, jid_full(jid)); 00352 if(ritem == NULL) ritem = xhash_get(user->roster, jid_user(jid)); 00353 if(ritem == NULL) ritem = xhash_get(user->roster, jid->domain); 00354 00355 /* got it, do the check */ 00356 if(ritem != NULL) 00357 for(i = 0; i < ritem->ngroups; i++) 00358 if(strcmp(scan->group, ritem->groups[i]) == 0) 00359 match = 1; 00360 00361 break; 00362 00363 case zebra_S10N: 00364 /* roster item check - get the roster item, node@dom/res, then node@dom, then dom */ 00365 ritem = xhash_get(user->roster, jid_full(jid)); 00366 if(ritem == NULL) ritem = xhash_get(user->roster, jid_user(jid)); 00367 if(ritem == NULL) ritem = xhash_get(user->roster, jid->domain); 00368 00369 /* got it, do the check */ 00370 if(ritem != NULL) 00371 if(scan->to == ritem->to && scan->from == ritem->from) 00372 match = 1; 00373 00374 break; 00375 } 00376 00377 /* if we matched a rule, we have to do packet block matching */ 00378 if(match) { 00379 /* no packet blocking, matching done */ 00380 if(scan->block == block_NONE) 00381 return scan->deny; 00382 00383 /* incoming checks block_MESSAGE, block_PRES_IN and block_IQ */ 00384 if(in) { 00385 if(ptype & pkt_MESSAGE && scan->block & block_MESSAGE) 00386 return scan->deny; 00387 if(ptype & pkt_PRESENCE && scan->block & block_PRES_IN) 00388 return scan->deny; 00389 if(ptype & pkt_IQ && scan->block & block_IQ) 00390 return scan->deny; 00391 } else if((ptype & pkt_PRESENCE && scan->block & block_PRES_OUT && ptype != pkt_PRESENCE_PROBE) || 00392 (ptype & pkt_MESSAGE && scan->block & block_MESSAGE)) { 00393 /* outgoing check, block_PRES_OUT */ 00394 /* XXX and block_MESSAGE for XEP-0191 while it violates XEP-0016 */ 00395 return scan->deny; 00396 } 00397 } 00398 } 00399 00400 /* didn't match the list, so allow */ 00401 return 0; 00402 } 00403 00405 static mod_ret_t _privacy_in_router(mod_instance_t mi, pkt_t pkt) { 00406 module_t mod = mi->mod; 00407 user_t user; 00408 zebra_t z; 00409 sess_t sess = NULL; 00410 zebra_list_t zlist = NULL; 00411 00412 /* if its coming to the sm, let it in */ 00413 if(pkt->to == NULL || pkt->to->node[0] == '\0') 00414 return mod_PASS; 00415 00416 /* get the user */ 00417 user = user_load(mod->mm->sm, pkt->to); 00418 if(user == NULL) { 00419 log_debug(ZONE, "no user %s, passing packet", jid_user(pkt->to)); 00420 return mod_PASS; 00421 } 00422 00423 /* get our lists */ 00424 z = (zebra_t) user->module_data[mod->index]; 00425 00426 /* find a session */ 00427 if(*pkt->to->resource != '\0') 00428 sess = sess_match(user, pkt->to->resource); 00429 00430 /* didn't match a session, so use the top session */ 00431 if(sess == NULL) 00432 sess = user->top; 00433 00434 /* get the active list for the session */ 00435 if(sess != NULL && sess->module_data[mod->index] != NULL) 00436 zlist = ((privacy_t) sess->module_data[mod->index])->active; 00437 00438 /* no active list, so use the default list */ 00439 if(zlist == NULL) 00440 zlist = z->def; 00441 00442 /* no list, so allow everything */ 00443 if(zlist == NULL) 00444 return mod_PASS; 00445 00446 /* figure out the action */ 00447 if(_privacy_action(user, zlist, pkt->from, pkt->type, 1) == 0) 00448 return mod_PASS; 00449 00450 /* deny */ 00451 log_debug(ZONE, "denying incoming packet based on privacy policy"); 00452 00453 /* iqs get special treatment */ 00454 if(pkt->type == pkt_IQ || pkt->type == pkt_IQ_SET) 00455 return -stanza_err_FEATURE_NOT_IMPLEMENTED; 00456 00457 /* drop it */ 00458 pkt_free(pkt); 00459 return mod_HANDLED; 00460 } 00461 00463 static mod_ret_t _privacy_out_router(mod_instance_t mi, pkt_t pkt) { 00464 module_t mod = mi->mod; 00465 user_t user; 00466 zebra_t z; 00467 sess_t sess = NULL; 00468 zebra_list_t zlist = NULL; 00469 int err, ns; 00470 00471 /* if its coming from the sm, let it go */ 00472 if(pkt->from == NULL || pkt->from->node[0] == '\0') 00473 return mod_PASS; 00474 00475 /* get the user */ 00476 user = user_load(mod->mm->sm, pkt->from); 00477 if(user == NULL) { 00478 log_debug(ZONE, "no user %s, passing packet", jid_user(pkt->to)); 00479 return mod_PASS; 00480 } 00481 00482 /* get our lists */ 00483 z = (zebra_t) user->module_data[mod->index]; 00484 00485 /* find a session */ 00486 if(*pkt->from->resource != '\0') 00487 sess = sess_match(user, pkt->from->resource); 00488 00489 /* get the active list for the session */ 00490 if(sess != NULL && sess->module_data[mod->index] != NULL) 00491 zlist = ((privacy_t) sess->module_data[mod->index])->active; 00492 00493 /* no active list, so use the default list */ 00494 if(zlist == NULL) 00495 zlist = z->def; 00496 00497 /* no list, so allow everything */ 00498 if(zlist == NULL) 00499 return mod_PASS; 00500 00501 /* figure out the action */ 00502 if(_privacy_action(user, zlist, pkt->to, pkt->type, 0) == 0) 00503 return mod_PASS; 00504 00505 /* deny */ 00506 log_debug(ZONE, "denying outgoing packet based on privacy policy"); 00507 00508 /* messages get special treatment */ 00509 if(pkt->type & pkt_MESSAGE) { 00510 /* hack the XEP-0191 error in */ 00511 pkt_error(pkt, stanza_err_NOT_ACCEPTABLE); 00512 err = nad_find_elem(pkt->nad, 1, -1, "error", 1); 00513 ns = nad_add_namespace(pkt->nad, urn_BLOCKING_ERR, NULL); 00514 nad_insert_elem(pkt->nad, err, ns, "blocked", NULL); 00515 pkt_sess(pkt, sess); 00516 return mod_HANDLED; 00517 } 00518 00519 /* drop it */ 00520 pkt_free(pkt); 00521 return mod_HANDLED; 00522 } 00523 00525 static void _privacy_result_builder(xht zhash, const char *name, void *val, void *arg) { 00526 zebra_list_t zlist = (zebra_list_t) val; 00527 pkt_t pkt = (pkt_t) arg; 00528 int ns, query, list, item; 00529 zebra_item_t zitem; 00530 char order[14]; 00531 00532 ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL); 00533 query = nad_find_elem(pkt->nad, 1, ns, "query", 1); 00534 00535 list = nad_insert_elem(pkt->nad, query, ns, "list", NULL); 00536 nad_set_attr(pkt->nad, list, -1, "name", zlist->name, 0); 00537 00538 /* run through the items and build the nad */ 00539 for(zitem = zlist->items; zitem != NULL; zitem = zitem->next) { 00540 item = nad_insert_elem(pkt->nad, list, ns, "item", NULL); 00541 00542 switch(zitem->type) { 00543 case zebra_JID: 00544 nad_set_attr(pkt->nad, item, -1, "type", "jid", 0); 00545 nad_set_attr(pkt->nad, item, -1, "value", jid_full(zitem->jid), 0); 00546 break; 00547 00548 case zebra_GROUP: 00549 nad_set_attr(pkt->nad, item, -1, "type", "group", 0); 00550 nad_set_attr(pkt->nad, item, -1, "value", zitem->group, 0); 00551 break; 00552 00553 case zebra_S10N: 00554 nad_set_attr(pkt->nad, item, -1, "type", "subscription", 0); 00555 00556 if(zitem->to == 1 && zitem->from == 1) 00557 nad_set_attr(pkt->nad, item, -1, "value", "both", 4); 00558 else if(zitem->to == 1) 00559 nad_set_attr(pkt->nad, item, -1, "value", "to", 2); 00560 else if(zitem->from == 1) 00561 nad_set_attr(pkt->nad, item, -1, "value", "from", 4); 00562 else 00563 nad_set_attr(pkt->nad, item, -1, "value", "none", 4); 00564 00565 break; 00566 00567 case zebra_NONE: 00568 break; 00569 } 00570 00571 if(zitem->deny) 00572 nad_set_attr(pkt->nad, item, -1, "action", "deny", 4); 00573 else 00574 nad_set_attr(pkt->nad, item, -1, "action", "allow", 5); 00575 00576 snprintf(order, 14, "%d", zitem->order); 00577 order[13] = '\0'; 00578 00579 nad_set_attr(pkt->nad, item, -1, "order", order, 0); 00580 00581 if(zitem->block & block_MESSAGE) 00582 nad_insert_elem(pkt->nad, item, ns, "message", NULL); 00583 if(zitem->block & block_PRES_IN) 00584 nad_insert_elem(pkt->nad, item, ns, "presence-in", NULL); 00585 if(zitem->block & block_PRES_OUT) 00586 nad_insert_elem(pkt->nad, item, ns, "presence-out", NULL); 00587 if(zitem->block & block_IQ) 00588 nad_insert_elem(pkt->nad, item, ns, "iq", NULL); 00589 } 00590 } 00591 00593 static void _privacy_lists_result_builder(const char *name, int namelen, void *val, void *arg) { 00594 zebra_list_t zlist = (zebra_list_t) val; 00595 pkt_t pkt = (pkt_t) arg; 00596 int ns, query, list; 00597 00598 ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL); 00599 query = nad_find_elem(pkt->nad, 1, ns, "query", 1); 00600 00601 list = nad_insert_elem(pkt->nad, query, ns, "list", NULL); 00602 nad_set_attr(pkt->nad, list, -1, "name", zlist->name, 0); 00603 } 00604 00608 static void _unblock_jid(user_t user, storage_t st, zebra_list_t zlist, jid_t jid) { 00609 char filter[1024]; 00610 zebra_item_t scan; 00611 sess_t sscan; 00612 jid_t notify_jid = NULL; 00613 00614 for(scan = zlist->items; scan != NULL; scan = scan->next) { 00615 if(scan->type == zebra_JID && scan->deny && (jid == NULL || jid_compare_full(scan->jid, jid) == 0)) { 00616 if(zlist->items == scan) { 00617 zlist->items = scan->next; 00618 if(zlist->items != NULL) 00619 zlist->items->prev = NULL; 00620 } else { 00621 assert(scan->prev != NULL); 00622 scan->prev->next = scan->next; 00623 if(scan->next != NULL) 00624 scan->next->prev = scan->prev; 00625 } 00626 00627 if (zlist->last == scan) 00628 zlist->last = scan->prev; 00629 00630 /* and from the storage */ 00631 sprintf(filter, "(&(list=%zu:%s)(type=3:jid)(value=%zu:%s))", 00632 strlen(urn_BLOCKING), urn_BLOCKING, strlen(jid_full(scan->jid)), jid_full(scan->jid)); 00633 storage_delete(st, "privacy-items", jid_user(user->jid), filter); 00634 00635 /* set jid for notify */ 00636 notify_jid = scan->jid; 00637 } 00638 00639 /* update unblocked contact with presence information of all sessions */ 00640 00641 /* XXX NOTE !!! There is a possibility that we notify more than once 00642 * if user edited the privacy list manually, not with XEP-0191. 00643 * Well... We're going to live with it. ;-) */ 00644 if(notify_jid != NULL && pres_trust(user, notify_jid)) 00645 for(sscan = user->sessions; sscan != NULL; sscan = sscan->next) { 00646 /* do not update if session is not available, 00647 * we sent presence direct or got error bounce */ 00648 if(!sscan->available || jid_search(sscan->A, notify_jid) || jid_search(sscan->E, notify_jid)) 00649 continue; 00650 00651 log_debug(ZONE, "updating unblocked %s with presence from %s", jid_full(notify_jid), jid_full(sscan->jid)); 00652 pkt_router(pkt_dup(sscan->pres, jid_full(notify_jid), jid_full(sscan->jid))); 00653 } 00654 } 00655 } 00656 00658 static mod_ret_t _privacy_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) { 00659 module_t mod = mi->mod; 00660 int ns, query, list, name, active, def, item, type, value, action, order, blocking, jid, push = 0; 00661 char corder[14], str[256], filter[1024]; 00662 zebra_t z; 00663 zebra_list_t zlist, old; 00664 pool_t p; 00665 zebra_item_t zitem, scan; 00666 sess_t sscan; 00667 jid_t jidt; 00668 pkt_t result; 00669 os_t os; 00670 os_object_t o; 00671 st_ret_t ret; 00672 00673 /* we only want to play with iq:privacy and urn:xmpp:blocking packets */ 00674 if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || (pkt->ns != ns_PRIVACY && pkt->ns != ns_BLOCKING)) 00675 return mod_PASS; 00676 00677 /* if it has a to, throw it out */ 00678 if(pkt->to != NULL) 00679 return -stanza_err_BAD_REQUEST; 00680 00681 /* get our lists */ 00682 z = (zebra_t) sess->user->module_data[mod->index]; 00683 00684 /* create session privacy description */ 00685 if(sess->module_data[mod->index] == NULL) 00686 sess->module_data[mod->index] = (void *) pmalloco(sess->p, sizeof(struct privacy_st)); 00687 00688 /* handle XEP-0191: Simple Communications Blocking 00689 * as simplified frontend to default privacy list */ 00690 if(pkt->ns == ns_BLOCKING) { 00691 if(pkt->type == pkt_IQ_SET) { 00692 /* find out what to do */ 00693 int block; 00694 ns = nad_find_scoped_namespace(pkt->nad, urn_BLOCKING, NULL); 00695 blocking = nad_find_elem(pkt->nad, 1, ns, "block", 1); 00696 if(blocking >= 0) 00697 block = 1; 00698 else { 00699 blocking = nad_find_elem(pkt->nad, 1, ns, "unblock", 1); 00700 if(blocking >= 0) 00701 block = 0; 00702 else 00703 return -stanza_err_BAD_REQUEST; 00704 } 00705 00706 /* if there is no default list, create one */ 00707 if(!z->def) { 00708 /* remove any previous one */ 00709 if((zlist = xhash_get(z->lists, urn_BLOCKING))) { 00710 pool_free(zlist->p); 00711 sprintf(filter, "(list=%zu:%s)", strlen(urn_BLOCKING), urn_BLOCKING); 00712 storage_delete(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), filter); 00713 } 00714 00715 /* create new zebra list with name 'urn:xmpp:blocking' */ 00716 p = pool_new(); 00717 zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st)); 00718 zlist->p = p; 00719 zlist->name = pstrdup(p, urn_BLOCKING); 00720 xhash_put(z->lists, zlist->name, (void *) zlist); 00721 00722 /* make it default */ 00723 z->def = zlist; 00724 00725 /* and in the storage */ 00726 os = os_new(); 00727 o = os_object_new(os); 00728 os_object_put(o, "default", zlist->name, os_type_STRING); 00729 ret = storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os); 00730 os_free(os); 00731 if(ret != st_SUCCESS) 00732 return -stanza_err_INTERNAL_SERVER_ERROR; 00733 00734 log_debug(ZONE, "blocking created '%s' privacy list and set it default", zlist->name); 00735 } else { 00736 /* use the default one */ 00737 zlist = z->def; 00738 } 00739 /* activate this list */ 00740 ((privacy_t) sess->module_data[mod->index])->active = zlist; 00741 log_debug(ZONE, "session '%s' has now active list '%s'", jid_full(sess->jid), zlist->name); 00742 00743 item = nad_find_elem(pkt->nad, blocking, ns, "item", 1); 00744 if(item < 0) { 00745 if(block) { 00746 /* cannot block unknown */ 00747 return -stanza_err_BAD_REQUEST; 00748 } else { 00749 /* unblock all */ 00750 _unblock_jid(sess->user, mod->mm->sm->st, zlist, NULL); 00751 00752 /* mark to send blocklist push */ 00753 push = 1; 00754 } 00755 } 00756 00757 /* loop over the items */ 00758 while(item >= 0) { 00759 /* extract jid */ 00760 jid = nad_find_attr(pkt->nad, item, -1, "jid", 0); 00761 if(jid < 0) 00762 return -stanza_err_BAD_REQUEST; 00763 00764 jidt = jid_new(NAD_AVAL(pkt->nad, jid), NAD_AVAL_L(pkt->nad, jid)); 00765 if(jidt == NULL) 00766 return -stanza_err_BAD_REQUEST; 00767 00768 /* find blockitem in the list */ 00769 for(scan = zlist->items; scan != NULL; scan = scan->next) 00770 if(scan->type == zebra_JID && jid_compare_full(scan->jid, jidt) == 0) 00771 break; 00772 00773 /* take action */ 00774 if(block) { 00775 if(scan != NULL && scan->deny && scan->block == block_NONE) { 00776 push = 0; 00777 } else { 00778 /* first make us unavailable if user is on roster */ 00779 if(pres_trust(sess->user, jidt)) 00780 for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) { 00781 /* do not update if session is not available, 00782 * we sent presence direct or got error bounce */ 00783 if(!sscan->available || jid_search(sscan->A, jidt) || jid_search(sscan->E, jidt)) 00784 continue; 00785 00786 log_debug(ZONE, "forcing unavailable to %s from %s after block", jid_full(jidt), jid_full(sscan->jid)); 00787 pkt_router(pkt_create(sess->user->sm, "presence", "unavailable", jid_full(jidt), jid_full(sscan->jid))); 00788 } 00789 00790 /* new item */ 00791 zitem = (zebra_item_t) pmalloco(zlist->p, sizeof(struct zebra_item_st)); 00792 zitem->type = zebra_JID; 00793 00794 zitem->jid = jid_new(NAD_AVAL(pkt->nad, jid), NAD_AVAL_L(pkt->nad, jid)); 00795 pool_cleanup(zlist->p, (void *) jid_free, zitem->jid); 00796 zitem->deny = 1; 00797 zitem->block = block_NONE; 00798 00799 /* insert it in front of list */ 00800 zitem->order = 0; 00801 if(zlist->last == NULL) { 00802 zlist->items = zlist->last = zitem; 00803 } else { 00804 zitem->next = zlist->items; 00805 zlist->items->prev = zitem; 00806 zlist->items = zitem; 00807 } 00808 00809 /* and into the storage backend */ 00810 os = os_new(); 00811 o = os_object_new(os); 00812 os_object_put(o, "list", zlist->name, os_type_STRING); 00813 os_object_put(o, "type", "jid", os_type_STRING); 00814 os_object_put(o, "value", jid_full(zitem->jid), os_type_STRING); 00815 os_object_put(o, "deny", &zitem->deny, os_type_BOOLEAN); 00816 os_object_put(o, "order", &zitem->order, os_type_INTEGER); 00817 os_object_put(o, "block", &zitem->block, os_type_INTEGER); 00818 ret = storage_put(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), os); 00819 os_free(os); 00820 if(ret != st_SUCCESS) { 00821 jid_free(jidt); 00822 return -stanza_err_INTERNAL_SERVER_ERROR; 00823 } 00824 00825 /* mark to send blocklist push */ 00826 push = 1; 00827 } 00828 } else { 00829 /* unblock action */ 00830 if(scan != NULL && scan->deny) { 00831 /* remove all jid deny ocurrences from the privacy list */ 00832 _unblock_jid(sess->user, mod->mm->sm->st, zlist, jidt); 00833 00834 /* mark to send blocklist push */ 00835 push = 1; 00836 } else { 00837 jid_free(jidt); 00838 return -stanza_err_ITEM_NOT_FOUND; 00839 } 00840 } 00841 00842 jid_free(jidt); 00843 00844 /* next item */ 00845 item = nad_find_elem(pkt->nad, item, ns, "item", 0); 00846 } 00847 00848 /* return empty result */ 00849 result = pkt_create(pkt->sm, "iq", "result", NULL, NULL); 00850 pkt_id(pkt, result); 00851 pkt_sess(result, sess); 00852 00853 /* blocklist push */ 00854 if(push) { 00855 for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) { 00856 /* don't push to us or to anyone who hasn't requested blocklist */ 00857 if(sscan == sess || sscan->module_data[mod->index] == NULL || ((privacy_t) sscan->module_data[mod->index])->blocklist == 0) 00858 continue; 00859 00860 result = pkt_dup(pkt, jid_full(sscan->jid), NULL); 00861 if(result->from != NULL) { 00862 jid_free(result->from); 00863 nad_set_attr(result->nad, 1, -1, "from", NULL, 0); 00864 } 00865 pkt_id_new(result); 00866 pkt_sess(result, sscan); 00867 } 00868 } 00869 00870 /* and done with request */ 00871 pkt_free(pkt); 00872 return mod_HANDLED; 00873 } 00874 00875 /* it's a get */ 00876 ns = nad_find_scoped_namespace(pkt->nad, urn_BLOCKING, NULL); 00877 blocking = nad_find_elem(pkt->nad, 1, ns, "blocklist", 1); 00878 if(blocking < 0) 00879 return -stanza_err_BAD_REQUEST; 00880 00881 result = pkt_create(pkt->sm, "iq", "result", NULL, NULL); 00882 pkt_id(pkt, result); 00883 ns = nad_add_namespace(result->nad, urn_BLOCKING, NULL); 00884 blocking = nad_insert_elem(result->nad, 1, ns, "blocklist", NULL); 00885 00886 /* insert items only from the default list */ 00887 if(z->def != NULL) { 00888 log_debug(ZONE, "blocking list is '%s'", z->def->name); 00889 zlist = xhash_get(z->lists, z->def->name); 00890 /* run through the items and build the nad */ 00891 for(zitem = zlist->items; zitem != NULL; zitem = zitem->next) { 00892 /* we're interested in items type 'jid' with action 'deny' only */ 00893 if(zitem->type == zebra_JID && zitem->deny) { 00894 item = nad_insert_elem(result->nad, blocking, -1, "item", NULL); 00895 nad_set_attr(result->nad, item, -1, "jid", jid_full(zitem->jid), 0); 00896 } 00897 } 00898 00899 /* mark that the blocklist was requested */ 00900 ((privacy_t) sess->module_data[mod->index])->blocklist = 1; 00901 } 00902 00903 /* give it to the session */ 00904 pkt_sess(result, sess); 00905 pkt_free(pkt); 00906 return mod_HANDLED; 00907 } 00908 00909 /* else handle XEP-0016: Privacy Lists */ 00910 00911 /* find the query */ 00912 ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL); 00913 query = nad_find_elem(pkt->nad, 1, ns, "query", 1); 00914 if(query < 0) 00915 return -stanza_err_BAD_REQUEST; 00916 00917 /* update lists or set the active list */ 00918 if(pkt->type == pkt_IQ_SET) { 00919 /* find out what we're doing */ 00920 list = nad_find_elem(pkt->nad, query, ns, "list", 1); 00921 active = nad_find_elem(pkt->nad, query, ns, "active", 1); 00922 def = nad_find_elem(pkt->nad, query, ns, "default", 1); 00923 00924 /* we need something to do, but we can't do it all at once */ 00925 if((list < 0 && active < 0 && def < 0) || (list >= 0 && (active >=0 || def >= 0))) 00926 return -stanza_err_BAD_REQUEST; 00927 00928 /* loop over any/all lists and store them */ 00929 if(list >= 0) { 00930 /* only allowed to change one list at a time */ 00931 if(nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0) 00932 return -stanza_err_BAD_REQUEST; 00933 00934 /* get the list name */ 00935 name = nad_find_attr(pkt->nad, list, -1, "name", NULL); 00936 if(name < 0) { 00937 log_debug(ZONE, "no list name specified, failing request"); 00938 return -stanza_err_BAD_REQUEST; 00939 } 00940 00941 snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name)); 00942 str[255] = '\0'; 00943 00944 log_debug(ZONE, "updating list %s", str); 00945 00946 /* make a new one */ 00947 p = pool_new(); 00948 00949 zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st)); 00950 00951 zlist->p = p; 00952 zlist->name = pstrdup(p, str); 00953 00954 os = os_new(); 00955 00956 /* loop over the items */ 00957 item = nad_find_elem(pkt->nad, list, ns, "item", 1); 00958 while(item >= 0) { 00959 /* extract things */ 00960 type = nad_find_attr(pkt->nad, item, -1, "type", 0); 00961 value = nad_find_attr(pkt->nad, item, -1, "value", 0); 00962 action = nad_find_attr(pkt->nad, item, -1, "action", 0); 00963 order = nad_find_attr(pkt->nad, item, -1, "order", 0); 00964 00965 /* sanity */ 00966 if(action < 0 || order < 0 || (type >= 0 && value < 0)) { 00967 pool_free(p); 00968 os_free(os); 00969 return -stanza_err_BAD_REQUEST; 00970 } 00971 00972 /* new item */ 00973 zitem = (zebra_item_t) pmalloco(p, sizeof(struct zebra_item_st)); 00974 00975 /* have to store it too */ 00976 o = os_object_new(os); 00977 os_object_put(o, "list", zlist->name, os_type_STRING); 00978 00979 /* type & value */ 00980 if(type >= 0) { 00981 if(NAD_AVAL_L(pkt->nad, type) == 3 && strncmp("jid", NAD_AVAL(pkt->nad, type), 3) == 0) { 00982 zitem->type = zebra_JID; 00983 00984 zitem->jid = jid_new(NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value)); 00985 if(zitem->jid == NULL) { 00986 log_debug(ZONE, "invalid jid '%.*s', failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value)); 00987 pool_free(p); 00988 os_free(os); 00989 return -stanza_err_BAD_REQUEST; 00990 } 00991 00992 pool_cleanup(p, (void *) jid_free, zitem->jid); 00993 00994 log_debug(ZONE, "jid item with value '%s'", jid_full(zitem->jid)); 00995 00996 os_object_put(o, "type", "jid", os_type_STRING); 00997 os_object_put(o, "value", jid_full(zitem->jid), os_type_STRING); 00998 } 00999 01000 else if(NAD_AVAL_L(pkt->nad, type) == 5 && strncmp("group", NAD_AVAL(pkt->nad, type), 5) == 0) { 01001 zitem->type = zebra_GROUP; 01002 01003 zitem->group = pstrdupx(zlist->p, NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value)); 01004 01005 /* !!! check if the group exists */ 01006 01007 log_debug(ZONE, "group item with value '%s'", zitem->group); 01008 01009 os_object_put(o, "type", "group", os_type_STRING); 01010 os_object_put(o, "value", zitem->group, os_type_STRING); 01011 } 01012 01013 else if(NAD_AVAL_L(pkt->nad, type) == 12 && strncmp("subscription", NAD_AVAL(pkt->nad, type), 12) == 0) { 01014 zitem->type = zebra_S10N; 01015 01016 os_object_put(o, "type", "subscription", os_type_STRING); 01017 01018 if(NAD_AVAL_L(pkt->nad, value) == 2 && strncmp("to", NAD_AVAL(pkt->nad, value), 2) == 0) { 01019 zitem->to = 1; 01020 os_object_put(o, "value", "to", os_type_STRING); 01021 } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("from", NAD_AVAL(pkt->nad, value), 4) == 0) { 01022 zitem->from = 1; 01023 os_object_put(o, "value", "from", os_type_STRING); 01024 } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("both", NAD_AVAL(pkt->nad, value), 4) == 0) { 01025 zitem->to = zitem->from = 1; 01026 os_object_put(o, "value", "both", os_type_STRING); 01027 } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("none", NAD_AVAL(pkt->nad, value), 4) == 0) 01028 os_object_put(o, "value", "none", os_type_STRING); 01029 else { 01030 log_debug(ZONE, "invalid value '%.*s' on s10n item, failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value)); 01031 pool_free(p); 01032 os_free(os); 01033 return -stanza_err_BAD_REQUEST; 01034 } 01035 01036 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); 01037 } 01038 } 01039 01040 /* action */ 01041 if(NAD_AVAL_L(pkt->nad, action) == 4 && strncmp("deny", NAD_AVAL(pkt->nad, action), 4) == 0) { 01042 zitem->deny = 1; 01043 log_debug(ZONE, "deny rule"); 01044 } else if(NAD_AVAL_L(pkt->nad, action) == 5 && strncmp("allow", NAD_AVAL(pkt->nad, action), 5) == 0) { 01045 zitem->deny = 0; 01046 log_debug(ZONE, "allow rule"); 01047 } else { 01048 log_debug(ZONE, "unknown action '%.*s', failing request", NAD_AVAL_L(pkt->nad, action), NAD_AVAL(pkt->nad, action)); 01049 pool_free(p); 01050 os_free(os); 01051 return -stanza_err_BAD_REQUEST; 01052 } 01053 01054 os_object_put(o, "deny", &zitem->deny, os_type_BOOLEAN); 01055 01056 /* order */ 01057 snprintf(corder, 14, "%.*s", NAD_AVAL_L(pkt->nad, order), NAD_AVAL(pkt->nad, order)); 01058 corder[13] = '\0'; 01059 zitem->order = atoi(corder); 01060 01061 os_object_put(o, "order", &zitem->order, os_type_INTEGER); 01062 01063 /* block types */ 01064 if(nad_find_elem(pkt->nad, item, ns, "message", 1) >= 0) 01065 zitem->block |= block_MESSAGE; 01066 if(nad_find_elem(pkt->nad, item, ns, "presence-in", 1) >= 0) 01067 zitem->block |= block_PRES_IN; 01068 if(nad_find_elem(pkt->nad, item, ns, "presence-out", 1) >= 0) 01069 zitem->block |= block_PRES_OUT; 01070 if(nad_find_elem(pkt->nad, item, ns, "iq", 1) >= 0) 01071 zitem->block |= block_IQ; 01072 01073 /* merge block all */ 01074 if(zitem->block & block_MESSAGE && 01075 zitem->block & block_PRES_IN && 01076 zitem->block & block_PRES_OUT && 01077 zitem->block & block_IQ) 01078 zitem->block = block_NONE; 01079 01080 os_object_put(o, "block", &zitem->block, os_type_INTEGER); 01081 01082 /* insert it */ 01083 for(scan = zlist->items; scan != NULL; scan = scan->next) 01084 if(zitem->order < scan->order) 01085 break; 01086 01087 /* we're >= everyone, add us to the end */ 01088 if(scan == NULL) { 01089 if(zlist->last == NULL) 01090 zlist->items = zlist->last = zitem; 01091 else { 01092 zlist->last->next = zitem; 01093 zitem->prev = zlist->last; 01094 zlist->last = zitem; 01095 } 01096 } 01097 01098 /* insert just before scan */ 01099 else { 01100 if(zlist->items == scan) { 01101 zitem->next = zlist->items; 01102 zlist->items = zitem; 01103 scan->prev = zitem; 01104 } else { 01105 zitem->next = scan; 01106 zitem->prev = scan->prev; 01107 scan->prev->next = zitem; 01108 scan->prev = zitem; 01109 } 01110 } 01111 01112 /* next item */ 01113 item = nad_find_elem(pkt->nad, item, ns, "item", 0); 01114 } 01115 01116 /* write the whole list out */ 01117 sprintf(filter, "(list=%zu:%s)", strlen(zlist->name), zlist->name); 01118 01119 ret = storage_replace(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), filter, os); 01120 os_free(os); 01121 01122 /* failed! */ 01123 if(ret != st_SUCCESS) { 01124 pool_free(zlist->p); 01125 return -stanza_err_INTERNAL_SERVER_ERROR; 01126 } 01127 01128 /* old list pointer */ 01129 old = xhash_get(z->lists, zlist->name); 01130 01131 /* removed list */ 01132 if(zlist->items == NULL) { 01133 log_debug(ZONE, "removed list %s", zlist->name); 01134 xhash_zap(z->lists, zlist->name); 01135 pool_free(zlist->p); 01136 if(old != NULL) pool_free(old->p); 01137 zlist = NULL; 01138 } else { 01139 log_debug(ZONE, "updated list %s", zlist->name); 01140 xhash_put(z->lists, zlist->name, (void *) zlist); 01141 if(old != NULL) pool_free(old->p); 01142 } 01143 01144 /* if this was a new list, then noone has it active yet */ 01145 if(old != NULL) { 01146 01147 /* relink */ 01148 log_debug(ZONE, "relinking sessions"); 01149 01150 /* loop through sessions, relink */ 01151 for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) 01152 if(sscan->module_data[mod->index] != NULL && ((privacy_t) sscan->module_data[mod->index])->active == old) { 01153 ((privacy_t) sscan->module_data[mod->index])->active = zlist; 01154 log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sscan->jid), (zlist != NULL) ? zlist->name : "(NONE)"); 01155 } 01156 01157 /* default list */ 01158 if(z->def == old) { 01159 z->def = zlist; 01160 01161 if(zlist == NULL) { 01162 storage_delete(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL); 01163 log_debug(ZONE, "removed default list"); 01164 } 01165 01166 else { 01167 os = os_new(); 01168 o = os_object_new(os); 01169 01170 os_object_put(o, "default", zlist->name, os_type_STRING); 01171 01172 storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os); 01173 01174 os_free(os); 01175 01176 log_debug(ZONE, "default list is now '%s'", (zlist != NULL) ? zlist->name : "(NONE)"); 01177 } 01178 } 01179 } 01180 } 01181 01182 /* set the active list */ 01183 if(active >= 0) { 01184 name = nad_find_attr(pkt->nad, active, -1, "name", NULL); 01185 if(name < 0) { 01186 /* no name, no active list */ 01187 log_debug(ZONE, "clearing active list for session '%s'", jid_full(sess->jid)); 01188 ((privacy_t) sess->module_data[mod->index])->active = NULL; 01189 } 01190 01191 else { 01192 snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name)); 01193 str[255] = '\0'; 01194 01195 zlist = xhash_get(z->lists, str); 01196 if(zlist == NULL) { 01197 log_debug(ZONE, "request to make list '%s' active, but there's no such list", str); 01198 return -stanza_err_ITEM_NOT_FOUND; 01199 } 01200 01201 ((privacy_t) sess->module_data[mod->index])->active = zlist; 01202 01203 log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sess->jid), str); 01204 } 01205 } 01206 01207 /* set the default list */ 01208 if(def >= 0) { 01209 name = nad_find_attr(pkt->nad, def, -1, "name", NULL); 01210 if(name < 0) { 01211 /* no name, no default list */ 01212 log_debug(ZONE, "clearing default list for '%s'", jid_user(sess->user->jid)); 01213 z->def = NULL; 01214 } 01215 01216 else { 01217 snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name)); 01218 str[255] = '\0'; 01219 01220 zlist = xhash_get(z->lists, str); 01221 if(zlist == NULL) { 01222 log_debug(ZONE, "request to make list '%s' default, but there's no such list"); 01223 return -stanza_err_ITEM_NOT_FOUND; 01224 } 01225 01226 z->def = zlist; 01227 01228 os = os_new(); 01229 o = os_object_new(os); 01230 01231 os_object_put(o, "default", zlist->name, os_type_STRING); 01232 01233 storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os); 01234 01235 os_free(os); 01236 01237 log_debug(ZONE, "'%s' now has default list '%s'", jid_user(sess->user->jid), str); 01238 } 01239 } 01240 01241 /* done, let them know */ 01242 result = pkt_create(pkt->sm, "iq", "result", NULL, NULL); 01243 01244 pkt_id(pkt, result); 01245 01246 /* done with this */ 01247 pkt_free(pkt); 01248 01249 /* give it to the session */ 01250 pkt_sess(result, sess); 01251 01252 /* all done */ 01253 return mod_HANDLED; 01254 } 01255 01256 /* its a get */ 01257 01258 /* only allowed to request one list, if any */ 01259 list = nad_find_elem(pkt->nad, query, ns, "list", 1); 01260 if(list >= 0 && nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0) 01261 return -stanza_err_BAD_REQUEST; 01262 01263 result = pkt_create(pkt->sm, "iq", "result", NULL, NULL); 01264 01265 pkt_id(pkt, result); 01266 01267 ns = nad_add_namespace(result->nad, uri_PRIVACY, NULL); 01268 query = nad_insert_elem(result->nad, 1, ns, "query", NULL); 01269 01270 /* just do one */ 01271 if(list >= 0) { 01272 name = nad_find_attr(pkt->nad, list, -1, "name", NULL); 01273 01274 zlist = xhash_getx(z->lists, NAD_AVAL(pkt->nad, name), NAD_AVAL_L(pkt->nad, name)); 01275 if(zlist == NULL) 01276 return -stanza_err_ITEM_NOT_FOUND; 01277 01278 _privacy_result_builder(z->lists, zlist->name, (void *) zlist, (void *) result); 01279 } 01280 01281 else { 01282 /* walk the list hash and add the lists in */ 01283 xhash_walk(z->lists, _privacy_lists_result_builder, (void *) result); 01284 } 01285 01286 /* tell them about current active and default list if they asked for everything */ 01287 if(list < 0) { 01288 /* active */ 01289 if(((privacy_t) sess->module_data[mod->index])->active != NULL) { 01290 active = nad_insert_elem(result->nad, query, ns, "active", NULL); 01291 nad_set_attr(result->nad, active, -1, "name", ((privacy_t) sess->module_data[mod->index])->active->name, 0); 01292 } 01293 01294 /* and the default list */ 01295 if(z->def != NULL) { 01296 def = nad_insert_elem(result->nad, query, ns, "default", NULL); 01297 nad_set_attr(result->nad, def, -1, "name", z->def->name, 0); 01298 } 01299 } 01300 01301 /* give it to the session */ 01302 pkt_sess(result, sess); 01303 01304 /* done with this */ 01305 pkt_free(pkt); 01306 01307 /* all done */ 01308 return mod_HANDLED; 01309 } 01310 01311 static void _privacy_user_delete(mod_instance_t mi, jid_t jid) { 01312 log_debug(ZONE, "deleting privacy data for %s", jid_user(jid)); 01313 01314 storage_delete(mi->sm->st, "privacy-items", jid_user(jid), NULL); 01315 storage_delete(mi->sm->st, "privacy-default", jid_user(jid), NULL); 01316 } 01317 01318 static void _privacy_free(module_t mod) { 01319 sm_unregister_ns(mod->mm->sm, uri_PRIVACY); 01320 feature_unregister(mod->mm->sm, uri_PRIVACY); 01321 } 01322 01323 DLLEXPORT int module_init(mod_instance_t mi, char *arg) { 01324 module_t mod = mi->mod; 01325 01326 if (mod->init) return 0; 01327 01328 mod->user_load = _privacy_user_load; 01329 mod->in_router = _privacy_in_router; 01330 mod->out_router = _privacy_out_router; 01331 mod->in_sess = _privacy_in_sess; 01332 mod->user_delete = _privacy_user_delete; 01333 mod->free = _privacy_free; 01334 01335 ns_PRIVACY = sm_register_ns(mod->mm->sm, uri_PRIVACY); 01336 feature_register(mod->mm->sm, uri_PRIVACY); 01337 ns_BLOCKING = sm_register_ns(mod->mm->sm, urn_BLOCKING); 01338 feature_register(mod->mm->sm, urn_BLOCKING); 01339 01340 return 0; 01341 }