📄 mod_privacy.c
字号:
/* roster item check - get the roster item, node@dom/res, then node@dom, then dom */ ritem = xhash_get(user->roster, jid_full(jid)); if(ritem == NULL) ritem = xhash_get(user->roster, jid_user(jid)); if(ritem == NULL) ritem = xhash_get(user->roster, jid->domain); /* got it, do the check */ if(ritem != NULL) if(scan->to == ritem->to && scan->from == ritem->from) match = 1; break; } /* if we matched a rule, we have to do packet block matching */ if(match) { /* no packet blocking, matching done */ if(scan->block == block_NONE) return scan->deny; /* incoming checks block_MESSAGE, block_PRES_IN and block_IQ */ if(in) { if(ptype & pkt_MESSAGE && scan->block & block_MESSAGE) return scan->deny; if(ptype & pkt_PRESENCE && scan->block & block_PRES_IN) return scan->deny; if(ptype & pkt_IQ && scan->block & block_IQ) return scan->deny; } /* outgoing check, just block_PRES_OUT */ if(ptype & pkt_PRESENCE && scan->block & block_PRES_OUT) return scan->deny; } } /* didn't match the list, so allow */ return 0;}/** check incoming packets */static mod_ret_t _privacy_in_router(mod_instance_t mi, pkt_t pkt) { module_t mod = mi->mod; user_t user; zebra_t z; sess_t sess = NULL; zebra_list_t zlist = NULL; /* if its coming to the sm, let it in */ if(pkt->to == NULL || pkt->to->node[0] == '\0') return mod_PASS; /* get the user */ user = user_load(mod->mm->sm, pkt->to); if(user == NULL) { log_debug(ZONE, "no user %s, passing packet", jid_user(pkt->to)); return mod_PASS; } /* get our lists */ z = (zebra_t) user->module_data[mod->index]; /* find a session */ if(*pkt->to->resource != '\0') sess = sess_match(user, pkt->to->resource); /* didn't match a session, so use the top session */ if(sess == NULL) sess = user->top; /* get the active list for the session */ if(sess != NULL) zlist = (zebra_list_t) sess->module_data[mod->index]; /* no active list, so use the default list */ if(zlist == NULL) zlist = z->def; /* no list, so allow everything */ if(zlist == NULL) return mod_PASS; /* figure out the action */ if(_privacy_action(user, zlist, pkt->from, pkt->type, 1) == 0) return mod_PASS; /* deny */ log_debug(ZONE, "denying incoming packet based on privacy policy"); /* iqs get special treatment */ if(pkt->type == pkt_IQ || pkt->type == pkt_IQ_SET) return -stanza_err_FEATURE_NOT_IMPLEMENTED; /* drop it */ pkt_free(pkt); return mod_HANDLED;}/** check outgoing packets */static mod_ret_t _privacy_out_router(mod_instance_t mi, pkt_t pkt) { module_t mod = mi->mod; user_t user; zebra_t z; sess_t sess = NULL; zebra_list_t zlist = NULL; /* if its coming from the sm, let it go */ if(pkt->from == NULL || pkt->from->node[0] == '\0') return mod_PASS; /* get the user */ user = user_load(mod->mm->sm, pkt->from); if(user == NULL) { log_debug(ZONE, "no user %s, passing packet", jid_user(pkt->to)); return mod_PASS; } /* get our lists */ z = (zebra_t) user->module_data[mod->index]; /* find a session */ if(*pkt->from->resource != '\0') sess = sess_match(user, pkt->from->resource); /* get the active list for the session */ if(sess != NULL) zlist = (zebra_list_t) sess->module_data[mod->index]; /* no active list, so use the default list */ if(zlist == NULL) zlist = z->def; /* no list, so allow everything */ if(zlist == NULL) return mod_PASS; /* figure out the action */ if(_privacy_action(user, zlist, pkt->to, pkt->type, 0) == 0) return mod_PASS; /* deny */ log_debug(ZONE, "denying outgoing packet based on privacy policy"); /* drop it */ pkt_free(pkt); return mod_HANDLED;}/** add a list to the return packet */static void _privacy_result_builder(xht zhash, const char *name, void *val, void *arg) { zebra_list_t zlist = (zebra_list_t) val; pkt_t pkt = (pkt_t) arg; int ns, query, list, item; zebra_item_t zitem; char order[14]; ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL); query = nad_find_elem(pkt->nad, 1, ns, "query", 1); list = nad_insert_elem(pkt->nad, query, ns, "list", NULL); nad_set_attr(pkt->nad, list, -1, "name", zlist->name, 0); /* run through the items and build the nad */ for(zitem = zlist->items; zitem != NULL; zitem = zitem->next) { item = nad_insert_elem(pkt->nad, list, ns, "item", NULL); switch(zitem->type) { case zebra_JID: nad_set_attr(pkt->nad, item, -1, "type", "jid", 0); nad_set_attr(pkt->nad, item, -1, "value", jid_full(zitem->jid), 0); break; case zebra_GROUP: nad_set_attr(pkt->nad, item, -1, "type", "group", 0); nad_set_attr(pkt->nad, item, -1, "value", zitem->group, 0); break; case zebra_S10N: nad_set_attr(pkt->nad, item, -1, "type", "subscription", 0); if(zitem->to == 1 && zitem->from == 1) nad_set_attr(pkt->nad, item, -1, "value", "both", 4); else if(zitem->to == 1) nad_set_attr(pkt->nad, item, -1, "value", "to", 2); else if(zitem->from == 1) nad_set_attr(pkt->nad, item, -1, "value", "from", 4); else nad_set_attr(pkt->nad, item, -1, "value", "none", 4); break; case zebra_NONE: break; } if(zitem->deny) nad_set_attr(pkt->nad, item, -1, "action", "deny", 4); else nad_set_attr(pkt->nad, item, -1, "action", "allow", 5); snprintf(order, 14, "%d", zitem->order); order[13] = '\0'; nad_set_attr(pkt->nad, item, -1, "order", order, 0); if(zitem->block & block_MESSAGE) nad_insert_elem(pkt->nad, item, ns, "message", NULL); if(zitem->block & block_PRES_IN) nad_insert_elem(pkt->nad, item, ns, "presence-in", NULL); if(zitem->block & block_PRES_OUT) nad_insert_elem(pkt->nad, item, ns, "presence-out", NULL); if(zitem->block & block_IQ) nad_insert_elem(pkt->nad, item, ns, "iq", NULL); }}/** add a list to the return packet */static void _privacy_lists_result_builder(xht zhash, const char *name, void *val, void *arg) { zebra_list_t zlist = (zebra_list_t) val; pkt_t pkt = (pkt_t) arg; int ns, query, list; ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL); query = nad_find_elem(pkt->nad, 1, ns, "query", 1); list = nad_insert_elem(pkt->nad, query, ns, "list", NULL); nad_set_attr(pkt->nad, list, -1, "name", zlist->name, 0);}/** list management requests */static mod_ret_t _privacy_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) { module_t mod = mi->mod; int ns, query, list, name, active, def, item, type, value, action, order; char corder[14], str[256], filter[1024]; zebra_t z; zebra_list_t zlist, old; pool p; zebra_item_t zitem, scan; sess_t sscan; pkt_t result; os_t os; os_object_t o; st_ret_t ret; /* we only want to play with iq:privacy packets */ if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_PRIVACY) return mod_PASS; /* if it has a to, throw it out */ if(pkt->to != NULL) return -stanza_err_BAD_REQUEST; /* find the query */ ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL); query = nad_find_elem(pkt->nad, 1, ns, "query", 1); if(query < 0) return -stanza_err_BAD_REQUEST; /* get our lists */ z = (zebra_t) sess->user->module_data[mod->index]; /* update lists or set the active list */ if(pkt->type == pkt_IQ_SET) { /* find out what we're doing */ list = nad_find_elem(pkt->nad, query, ns, "list", 1); active = nad_find_elem(pkt->nad, query, ns, "active", 1); def = nad_find_elem(pkt->nad, query, ns, "default", 1); /* we need something to do, but we can't do it all at once */ if((list < 0 && active < 0 && def < 0) || (list >= 0 && (active >=0 || def >= 0))) return -stanza_err_BAD_REQUEST; /* loop over any/all lists and store them */ if(list >= 0) { /* only allowed to change one list at a time */ if(nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0) { /* hack the error in */ pkt_error(pkt, stanza_err_BAD_REQUEST); pkt_sess(pkt, sess); return mod_HANDLED; } /* get the list name */ name = nad_find_attr(pkt->nad, list, -1, "name", NULL); if(name < 0) { log_debug(ZONE, "no list name specified, failing request"); return -stanza_err_BAD_REQUEST; } snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name)); str[255] = '\0'; log_debug(ZONE, "updating list %s", str); /* make a new one */ p = pool_new(); zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st)); zlist->p = p; zlist->name = pstrdup(p, str); os = os_new(); /* loop over the items */ item = nad_find_elem(pkt->nad, list, ns, "item", 1); while(item >= 0) { /* extract things */ type = nad_find_attr(pkt->nad, item, -1, "type", 0); value = nad_find_attr(pkt->nad, item, -1, "value", 0); action = nad_find_attr(pkt->nad, item, -1, "action", 0); order = nad_find_attr(pkt->nad, item, -1, "order", 0); /* sanity */ if(action < 0 || order < 0 || (type >= 0 && value < 0)) { pool_free(p); os_free(os); return -stanza_err_BAD_REQUEST; } /* new item */ zitem = (zebra_item_t) pmalloco(p, sizeof(struct zebra_item_st)); /* have to store it too */ o = os_object_new(os); os_object_put(o, "list", zlist->name, os_type_STRING); /* type & value */ if(type >= 0) { if(NAD_AVAL_L(pkt->nad, type) == 3 && strncmp("jid", NAD_AVAL(pkt->nad, type), 3) == 0) { zitem->type = zebra_JID; zitem->jid = jid_new(mod->mm->sm->pc, NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value)); if(zitem->jid == NULL) { log_debug(ZONE, "invalid jid '%.*s', failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value)); pool_free(p); os_free(os); return -stanza_err_BAD_REQUEST; } pool_cleanup(p, free, zitem->jid); log_debug(ZONE, "jid item with value '%s'", jid_full(zitem->jid)); os_object_put(o, "type", "jid", os_type_STRING); os_object_put(o, "value", jid_full(zitem->jid), os_type_STRING); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -