~ubuntu-branches/ubuntu/oneiric/jabberd2/oneiric-security

« back to all changes in this revision

Viewing changes to sm/mod_privacy.c

  • Committer: Bazaar Package Importer
  • Author(s): Nicolai Spohrer
  • Date: 2008-08-12 16:13:43 UTC
  • mfrom: (1.1.3 upstream) (0.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20080812161343-6trz3r97dtevxd17
Tags: 2.2.1-1ubuntu1
* Merge with Debian unstable (LP: #257130), remaining changes:
  - debian/control:
    + Modify Maintainer field as per spec
    + Depend on libdb4.6-dev instead of libdb4.4-dev
    + Added Conflicts and Replaces: ..., jabber for jabberd2
  - debian/rules: Added libtoolize call (jabberd2 ships with
     an older ltmain.sh version that conflicts with the
     current libtool version)
  - debian/init: create /var/run/jabber directory with correct
     permissions
* Dropped changes:
  - Debian already depends on libpq-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include "sm.h"
22
22
 
23
23
/** @file sm/mod_privacy.c
24
 
  * @brief privacy lists
 
24
  * @brief XEP-0016 Privacy Lists and XEP-0191 Simple Comunications Blocking
25
25
  * @author Robert Norris
26
 
  * $Date: 2005/03/23 18:01:25 $
27
 
  * $Revision: 1.19.2.11 $
 
26
  * $Date: 2005/08/17 07:48:28 $
 
27
  * $Revision: 1.32 $
28
28
  */
29
29
 
 
30
static int ns_PRIVACY = 0;
 
31
static int ns_BLOCKING = 0;
 
32
 
30
33
typedef struct zebra_st         *zebra_t;
31
34
typedef struct zebra_list_st    *zebra_list_t;
32
35
typedef struct zebra_item_st    *zebra_item_t;
54
57
};
55
58
 
56
59
struct zebra_list_st {
57
 
    pool            p;
 
60
    pool_t          p;
58
61
 
59
62
    char            *name;
60
63
 
80
83
    zebra_item_t        next, prev;
81
84
};
82
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
 
83
94
/* union for xhash_iter_get to comply with strict-alias rules for gcc3 */
84
95
union xhashv
85
96
{
87
98
  zebra_list_t *z_val;
88
99
};
89
100
 
90
 
static void _privacy_free(zebra_t z) {
 
101
static void _privacy_free_z(zebra_t z) {
91
102
    zebra_list_t zlist;
92
103
    union xhashv xhv;
93
104
 
106
117
 
107
118
static void _privacy_user_free(zebra_t *z) {
108
119
    if(*z != NULL)
109
 
        _privacy_free(*z);
 
120
        _privacy_free_z(*z);
110
121
}
111
122
 
112
123
static int _privacy_user_load(mod_instance_t mi, user_t user) {
115
126
    os_t os;
116
127
    os_object_t o;
117
128
    zebra_list_t zlist;
118
 
    pool p;
 
129
    pool_t p;
119
130
    zebra_item_t zitem, scan;
120
131
    char *str;
121
132
 
124
135
    /* free if necessary */
125
136
    z = user->module_data[mod->index];
126
137
    if(z != NULL)
127
 
        _privacy_free(z);
 
138
        _privacy_free_z(z);
128
139
 
129
 
    z = (zebra_t) malloc(sizeof(struct zebra_st));
130
 
    memset(z, 0, sizeof(struct zebra_st));
 
140
    z = (zebra_t) calloc(1, sizeof(struct zebra_st));
131
141
 
132
142
    z->lists = xhash_new(101);
133
143
 
188
198
                if(zitem->type != zebra_NONE) {
189
199
                    if(!os_object_get_str(os, o, "value", &str)) {
190
200
                        log_debug(ZONE, "no value on non-fall-through item, dropping this item");
191
 
                        free(zitem);
192
201
                        continue;
193
202
                    }
194
203
 
195
204
                    switch(zitem->type) {
196
205
 
197
206
                        case zebra_JID:
198
 
                            zitem->jid = jid_new(user->sm->pc, str, strlen(str));
 
207
                            zitem->jid = jid_new(str, strlen(str));
199
208
                            if(zitem->jid == NULL) {
200
209
                                log_debug(ZONE, "invalid jid '%s' on item, dropping this item", str);
201
 
                                free(zitem);
202
210
                                continue;
203
211
                            }
204
212
 
205
 
                            pool_cleanup(zlist->p, free, zitem->jid);
 
213
                            pool_cleanup(zlist->p, (void *) jid_free, zitem->jid);
206
214
 
207
215
                            log_debug(ZONE, "jid item with value '%s'", jid_full(zitem->jid));
208
216
 
224
232
                                zitem->to = zitem->from = 1;
225
233
                            else if(strcmp(str, "none") != 0) {
226
234
                                log_debug(ZONE, "invalid value '%s' on s10n item, dropping this item", str);
227
 
                                free(zitem);
228
235
                                continue;
229
236
                            }
230
237
 
249
256
                os_object_get_int(os, o, "order", &(zitem->order));
250
257
                log_debug(ZONE, "order %d", zitem->order);
251
258
 
252
 
                os_object_get_int(os, o, "block", (int *) &(zitem->block));
 
259
                os_object_get_int(os, o, "block", &(zitem->block));
253
260
                log_debug(ZONE, "block 0x%x", zitem->block);
254
261
 
255
262
                /* insert it */
381
388
                    return scan->deny;
382
389
                if(ptype & pkt_IQ && scan->block & block_IQ)
383
390
                    return scan->deny;
384
 
            } else if(ptype & pkt_PRESENCE && scan->block & block_PRES_OUT && ptype != pkt_PRESENCE_PROBE) {
385
 
                /* outgoing check, just block_PRES_OUT */
 
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 */
386
395
                return scan->deny;
387
396
            }
388
397
        }
423
432
        sess = user->top;
424
433
 
425
434
    /* get the active list for the session */
426
 
    if(sess != NULL)
427
 
        zlist = (zebra_list_t) sess->module_data[mod->index];
 
435
    if(sess != NULL && sess->module_data[mod->index] != NULL)
 
436
        zlist = ((privacy_t) sess->module_data[mod->index])->active;
428
437
 
429
438
    /* no active list, so use the default list */
430
439
    if(zlist == NULL)
457
466
    zebra_t z;
458
467
    sess_t sess = NULL;
459
468
    zebra_list_t zlist = NULL;
 
469
    int err, ns;
460
470
 
461
471
    /* if its coming from the sm, let it go */
462
472
    if(pkt->from == NULL || pkt->from->node[0] == '\0')
477
487
        sess = sess_match(user, pkt->from->resource);
478
488
 
479
489
    /* get the active list for the session */
480
 
    if(sess != NULL)
481
 
        zlist = (zebra_list_t) sess->module_data[mod->index];
 
490
    if(sess != NULL && sess->module_data[mod->index] != NULL)
 
491
        zlist = ((privacy_t) sess->module_data[mod->index])->active;
482
492
 
483
493
    /* no active list, so use the default list */
484
494
    if(zlist == NULL)
495
505
    /* deny */
496
506
    log_debug(ZONE, "denying outgoing packet based on privacy policy");
497
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
 
498
519
    /* drop it */
499
520
    pkt_free(pkt);
500
521
    return mod_HANDLED;
581
602
    nad_set_attr(pkt->nad, list, -1, "name", zlist->name, 0);
582
603
}
583
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 */
 
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
            /* and from the storage */
 
627
            sprintf(filter, "(&(type=3:jid)(value=%i:%s)(deny=1)", strlen(jid_full(scan->jid)), jid_full(scan->jid));
 
628
            storage_delete(st, "privacy-items", jid_user(user->jid), filter);
 
629
 
 
630
            /* set jid for notify */
 
631
            notify_jid = scan->jid;
 
632
        }
 
633
 
 
634
        /* update unblocked contact with presence information of all sessions */
 
635
 
 
636
        /* XXX NOTE !!! There is a possibility that we notify more than once
 
637
         * if user edited the privacy list manually, not with XEP-0191.
 
638
         * Well... We're going to live with it. ;-) */
 
639
        if(notify_jid != NULL && pres_trust(user, notify_jid))
 
640
            for(sscan = user->sessions; sscan != NULL; sscan = sscan->next) {
 
641
                /* do not update if session is not available,
 
642
                 * we sent presence direct or got error bounce */
 
643
                if(!sscan->available || jid_search(sscan->A, notify_jid) || jid_search(sscan->E, notify_jid))
 
644
                    continue;
 
645
    
 
646
                log_debug(ZONE, "updating unblocked %s with presence from %s", jid_full(notify_jid), jid_full(sscan->jid));
 
647
                pkt_router(pkt_dup(sscan->pres, jid_full(notify_jid), jid_full(sscan->jid)));
 
648
            }
 
649
    }
 
650
}
 
651
 
584
652
/** list management requests */
585
653
static mod_ret_t _privacy_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
586
654
    module_t mod = mi->mod;
587
 
    int ns, query, list, name, active, def, item, type, value, action, order;
 
655
    int ns, query, list, name, active, def, item, type, value, action, order, blocking, jid, push = 0;
588
656
    char corder[14], str[256], filter[1024];
589
657
    zebra_t z;
590
658
    zebra_list_t zlist, old;
591
 
    pool p;
 
659
    pool_t p;
592
660
    zebra_item_t zitem, scan;
593
661
    sess_t sscan;
 
662
    jid_t jidt;
594
663
    pkt_t result;
595
664
    os_t os;
596
665
    os_object_t o;
597
666
    st_ret_t ret;
598
667
 
599
 
    /* we only want to play with iq:privacy packets */
600
 
    if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_PRIVACY)
 
668
    /* we only want to play with iq:privacy and urn:xmpp:blocking packets */
 
669
    if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || (pkt->ns != ns_PRIVACY && pkt->ns != ns_BLOCKING))
601
670
        return mod_PASS;
602
671
 
603
672
    /* if it has a to, throw it out */
604
673
    if(pkt->to != NULL)
605
674
        return -stanza_err_BAD_REQUEST;
606
675
 
 
676
    /* get our lists */
 
677
    z = (zebra_t) sess->user->module_data[mod->index];
 
678
 
 
679
    /* create session privacy description */
 
680
    if(sess->module_data[mod->index] == NULL)
 
681
        sess->module_data[mod->index] = (void *) pmalloco(sess->p, sizeof(struct privacy_st));
 
682
 
 
683
    /* handle XEP-0191: Simple Communications Blocking
 
684
     * as simplified frontend to default privacy list */
 
685
    if(pkt->ns == ns_BLOCKING) {
 
686
        if(pkt->type == pkt_IQ_SET) {
 
687
            /* find out what to do */
 
688
            int block;
 
689
            ns = nad_find_scoped_namespace(pkt->nad, urn_BLOCKING, NULL);
 
690
            blocking = nad_find_elem(pkt->nad, 1, ns, "block", 1);
 
691
            if(blocking >= 0)
 
692
                block = 1;
 
693
            else {
 
694
                blocking = nad_find_elem(pkt->nad, 1, ns, "unblock", 1);
 
695
                if(blocking >= 0)
 
696
                    block = 0;
 
697
                else
 
698
                    return -stanza_err_BAD_REQUEST;
 
699
            }
 
700
 
 
701
            /* if there is no default list, create one */
 
702
            if(!z->def) {
 
703
                /* remove any previous one */
 
704
                if((zlist = xhash_get(z->lists, urn_BLOCKING))) {
 
705
                    pool_free(zlist->p);
 
706
                    sprintf(filter, "(list=%i:%s)", strlen(urn_BLOCKING), urn_BLOCKING);
 
707
                    storage_delete(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), filter);
 
708
                }
 
709
 
 
710
                /* create new zebra list with name 'urn:xmpp:blocking' */
 
711
                p = pool_new();
 
712
                zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st));
 
713
                zlist->p = p;
 
714
                zlist->name = pstrdup(p, urn_BLOCKING);
 
715
                xhash_put(z->lists, zlist->name, (void *) zlist);
 
716
                
 
717
                /* make it default */
 
718
                z->def = zlist;
 
719
 
 
720
                /* and in the storage */
 
721
                os = os_new();
 
722
                o = os_object_new(os);
 
723
                os_object_put(o, "default", zlist->name, os_type_STRING);
 
724
                ret = storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os);
 
725
                os_free(os);
 
726
                if(ret != st_SUCCESS)
 
727
                    return -stanza_err_INTERNAL_SERVER_ERROR;
 
728
 
 
729
                log_debug(ZONE, "blocking created '%s' privacy list and set it default", zlist->name);
 
730
            } else {
 
731
                /* use the default one */
 
732
                zlist = z->def;
 
733
            }
 
734
            /* activate this list */
 
735
            ((privacy_t) sess->module_data[mod->index])->active = zlist;
 
736
            log_debug(ZONE, "session '%s' has now active list '%s'", jid_full(sess->jid), zlist->name);
 
737
 
 
738
            item = nad_find_elem(pkt->nad, blocking, ns, "item", 1);
 
739
            if(item < 0) {
 
740
                if(block) {
 
741
                    /* cannot block unknown */
 
742
                    return -stanza_err_BAD_REQUEST;
 
743
                } else {
 
744
                    /* unblock all */
 
745
                    _unblock_jid(sess->user, mod->mm->sm->st, zlist, NULL);
 
746
 
 
747
                    /* mark to send blocklist push */
 
748
                    push = 1;
 
749
                }
 
750
            }
 
751
 
 
752
            /* loop over the items */
 
753
            while(item >= 0) {
 
754
                /* extract jid */
 
755
                jid = nad_find_attr(pkt->nad, item, -1, "jid", 0);
 
756
                if(jid < 0)
 
757
                    return -stanza_err_BAD_REQUEST;
 
758
 
 
759
                jidt = jid_new(NAD_AVAL(pkt->nad, jid), NAD_AVAL_L(pkt->nad, jid));
 
760
                if(jidt == NULL)
 
761
                    return -stanza_err_BAD_REQUEST;
 
762
 
 
763
                /* find blockitem in the list */
 
764
                for(scan = zlist->items; scan != NULL; scan = scan->next)
 
765
                    if(scan->type == zebra_JID && jid_compare_full(scan->jid, jidt) == 0)
 
766
                        break;
 
767
 
 
768
                /* take action */
 
769
                if(block) {
 
770
                    if(scan != NULL && scan->deny && scan->block == block_NONE) {
 
771
                            push = 0;
 
772
                    } else {
 
773
                        /* first make us unavailable if user is on roster */
 
774
                        if(pres_trust(sess->user, jidt))
 
775
                            for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
 
776
                                /* do not update if session is not available,
 
777
                                 * we sent presence direct or got error bounce */
 
778
                                if(!sscan->available || jid_search(sscan->A, jidt) || jid_search(sscan->E, jidt))
 
779
                                    continue;
 
780
                        
 
781
                                log_debug(ZONE, "forcing unavailable to %s from %s after block", jid_full(jidt), jid_full(sscan->jid));
 
782
                                pkt_router(pkt_create(sess->user->sm, "presence", "unavailable", jid_full(jidt), jid_full(sscan->jid)));
 
783
                            }
 
784
 
 
785
                        /* new item */
 
786
                        zitem = (zebra_item_t) pmalloco(zlist->p, sizeof(struct zebra_item_st));
 
787
                        zitem->type = zebra_JID;
 
788
 
 
789
                        zitem->jid = jid_new(NAD_AVAL(pkt->nad, jid), NAD_AVAL_L(pkt->nad, jid));
 
790
                        pool_cleanup(zlist->p, (void *) jid_free, zitem->jid);
 
791
                        zitem->deny = 1;
 
792
                        zitem->block = block_NONE;
 
793
 
 
794
                        /* insert it in front of list */
 
795
                        zitem->order = 0;
 
796
                        if(zlist->last == NULL) {
 
797
                            zlist->items = zlist->last = zitem;
 
798
                        } else {
 
799
                            zitem->next = zlist->items;
 
800
                            zlist->items->prev = zitem;
 
801
                            zlist->items = zitem;
 
802
                        }
 
803
 
 
804
                        /* and into the storage backend */
 
805
                        os = os_new();
 
806
                        o = os_object_new(os);
 
807
                        os_object_put(o, "list", zlist->name, os_type_STRING);
 
808
                        os_object_put(o, "type", "jid", os_type_STRING);
 
809
                        os_object_put(o, "value", jid_full(zitem->jid), os_type_STRING);
 
810
                        os_object_put(o, "deny", &zitem->deny, os_type_BOOLEAN);
 
811
                        os_object_put(o, "order", &zitem->order, os_type_INTEGER);
 
812
                        os_object_put(o, "block", &zitem->block, os_type_INTEGER);
 
813
                        ret = storage_put(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), os);
 
814
                        os_free(os);
 
815
                        if(ret != st_SUCCESS) {
 
816
                            jid_free(jidt);
 
817
                            return -stanza_err_INTERNAL_SERVER_ERROR;
 
818
                        }
 
819
 
 
820
                        /* mark to send blocklist push */
 
821
                        push = 1;
 
822
                    }
 
823
                } else {
 
824
                    /* unblock action */
 
825
                    if(scan != NULL && scan->deny) {
 
826
                        /* remove all jid deny ocurrences from the privacy list */
 
827
                        _unblock_jid(sess->user, mod->mm->sm->st, zlist, jidt);
 
828
 
 
829
                        /* mark to send blocklist push */
 
830
                        push = 1;
 
831
                    } else {
 
832
                        jid_free(jidt);
 
833
                        return -stanza_err_ITEM_NOT_FOUND;
 
834
                    }
 
835
                }
 
836
 
 
837
                jid_free(jidt);
 
838
 
 
839
                /* next item */
 
840
                item = nad_find_elem(pkt->nad, item, ns, "item", 0);
 
841
            }
 
842
 
 
843
            /* return empty result */
 
844
            result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
 
845
            pkt_id(pkt, result);
 
846
            pkt_sess(result, sess);
 
847
 
 
848
            /* blocklist push */
 
849
            if(push) {
 
850
                for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
 
851
                    /* don't push to us or to anyone who hasn't requested blocklist */
 
852
                    if(sscan == sess || sscan->module_data[mod->index] == NULL || ((privacy_t) sscan->module_data[mod->index])->blocklist == 0)
 
853
                        continue;
 
854
 
 
855
                    result = pkt_dup(pkt, jid_full(sscan->jid), NULL);
 
856
                    if(result->from != NULL) {
 
857
                        jid_free(result->from);
 
858
                        nad_set_attr(result->nad, 1, -1, "from", NULL, 0);
 
859
                    }
 
860
                    pkt_id_new(result);
 
861
                    pkt_sess(result, sscan);
 
862
                }
 
863
            }
 
864
 
 
865
            /* and done with request */
 
866
            pkt_free(pkt);
 
867
            return mod_HANDLED;
 
868
        }
 
869
 
 
870
        /* it's a get */
 
871
        ns = nad_find_scoped_namespace(pkt->nad, urn_BLOCKING, NULL);
 
872
        blocking = nad_find_elem(pkt->nad, 1, ns, "blocklist", 1);
 
873
        if(blocking < 0)
 
874
            return -stanza_err_BAD_REQUEST;
 
875
 
 
876
        result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
 
877
        pkt_id(pkt, result);
 
878
        ns = nad_add_namespace(result->nad, urn_BLOCKING, NULL);
 
879
        blocking = nad_insert_elem(result->nad, 1, ns, "blocklist", NULL);
 
880
 
 
881
        /* insert items only from the default list */
 
882
        if(z->def != NULL) {
 
883
            log_debug(ZONE, "blocking list is '%s'", z->def->name);
 
884
            zlist = xhash_get(z->lists, z->def->name);
 
885
            /* run through the items and build the nad */
 
886
            for(zitem = zlist->items; zitem != NULL; zitem = zitem->next) {
 
887
                /* we're interested in items type 'jid' with action 'deny' only */
 
888
                if(zitem->type == zebra_JID && zitem->deny) {
 
889
                    item = nad_insert_elem(result->nad, blocking, -1, "item", NULL);
 
890
                    nad_set_attr(result->nad, item, -1, "jid", jid_full(zitem->jid), 0);
 
891
                }
 
892
            }
 
893
 
 
894
            /* mark that the blocklist was requested */
 
895
            ((privacy_t) sess->module_data[mod->index])->blocklist = 1;
 
896
        }
 
897
 
 
898
        /* give it to the session */
 
899
        pkt_sess(result, sess);
 
900
        pkt_free(pkt);
 
901
        return mod_HANDLED;
 
902
    }
 
903
 
 
904
    /* else handle XEP-0016: Privacy Lists */
 
905
 
607
906
    /* find the query */
608
907
    ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL);
609
908
    query = nad_find_elem(pkt->nad, 1, ns, "query", 1);
610
909
    if(query < 0)
611
910
        return -stanza_err_BAD_REQUEST;
612
911
 
613
 
    /* get our lists */
614
 
    z = (zebra_t) sess->user->module_data[mod->index];
615
 
 
616
912
    /* update lists or set the active list */
617
913
    if(pkt->type == pkt_IQ_SET) {
618
914
        /* find out what we're doing */
627
923
        /* loop over any/all lists and store them */
628
924
        if(list >= 0) {
629
925
            /* only allowed to change one list at a time */
630
 
            if(nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0) {
631
 
                /* hack the error in */
632
 
                pkt_error(pkt, stanza_err_BAD_REQUEST);
633
 
 
634
 
                pkt_sess(pkt, sess);
635
 
                return mod_HANDLED;
636
 
            }
 
926
            if(nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0)
 
927
                return -stanza_err_BAD_REQUEST;
637
928
 
638
929
            /* get the list name */
639
930
            name = nad_find_attr(pkt->nad, list, -1, "name", NULL);
685
976
                    if(NAD_AVAL_L(pkt->nad, type) == 3 && strncmp("jid", NAD_AVAL(pkt->nad, type), 3) == 0) {
686
977
                        zitem->type = zebra_JID;
687
978
 
688
 
                        zitem->jid = jid_new(mod->mm->sm->pc, NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value));
 
979
                        zitem->jid = jid_new(NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value));
689
980
                        if(zitem->jid == NULL) {
690
981
                            log_debug(ZONE, "invalid jid '%.*s', failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value));
691
982
                            pool_free(p);
693
984
                            return -stanza_err_BAD_REQUEST;
694
985
                        }
695
986
 
696
 
                        pool_cleanup(p, free, zitem->jid);
 
987
                        pool_cleanup(p, (void *) jid_free, zitem->jid);
697
988
 
698
989
                        log_debug(ZONE, "jid item with value '%s'", jid_full(zitem->jid));
699
990
 
774
1065
                if(nad_find_elem(pkt->nad, item, ns, "iq", 1) >= 0)
775
1066
                    zitem->block |= block_IQ;
776
1067
 
 
1068
                /* merge block all */
 
1069
                if(zitem->block & block_MESSAGE &&
 
1070
                   zitem->block & block_PRES_IN &&
 
1071
                   zitem->block & block_PRES_OUT &&
 
1072
                   zitem->block & block_IQ)
 
1073
                    zitem->block = block_NONE;
 
1074
 
777
1075
                os_object_put(o, "block", &zitem->block, os_type_INTEGER);
778
1076
 
779
1077
                /* insert it */
846
1144
 
847
1145
                /* loop through sessions, relink */
848
1146
                for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next)
849
 
                    if(sscan->module_data[mod->index] == old) {
850
 
                        sscan->module_data[mod->index] = (void *) zlist;
 
1147
                    if(sscan->module_data[mod->index] != NULL && ((privacy_t) sscan->module_data[mod->index])->active == old) {
 
1148
                        ((privacy_t) sscan->module_data[mod->index])->active = zlist;
851
1149
                        log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sscan->jid), (zlist != NULL) ? zlist->name : "(NONE)");
852
1150
                    }
853
1151
 
882
1180
            if(name < 0) {
883
1181
                /* no name, no active list */
884
1182
                log_debug(ZONE, "clearing active list for session '%s'", jid_full(sess->jid));
885
 
                sess->module_data[mod->index] = NULL;
 
1183
                ((privacy_t) sess->module_data[mod->index])->active = NULL;
886
1184
            }
887
1185
 
888
1186
            else {
892
1190
                zlist = xhash_get(z->lists, str);
893
1191
                if(zlist == NULL) {
894
1192
                    log_debug(ZONE, "request to make list '%s' active, but there's no such list", str);
895
 
 
896
 
                    /* hack the error in */
897
 
                    pkt_error(pkt, stanza_err_ITEM_NOT_FOUND);
898
 
 
899
 
                    pkt_sess(pkt, sess);
900
 
                    return mod_HANDLED;
 
1193
                    return -stanza_err_ITEM_NOT_FOUND;
901
1194
                }
902
1195
 
903
 
                sess->module_data[mod->index] = zlist;
 
1196
                ((privacy_t) sess->module_data[mod->index])->active = zlist;
904
1197
 
905
1198
                log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sess->jid), str);
906
1199
            }
922
1215
                zlist = xhash_get(z->lists, str);
923
1216
                if(zlist == NULL) {
924
1217
                    log_debug(ZONE, "request to make list '%s' default, but there's no such list");
925
 
 
926
 
                    /* hack the error in */
927
 
                    pkt_error(pkt, stanza_err_ITEM_NOT_FOUND);
928
 
 
929
 
                    pkt_sess(pkt, sess);
930
 
                    return mod_HANDLED;
 
1218
                    return -stanza_err_ITEM_NOT_FOUND;
931
1219
                }
932
1220
 
933
1221
                z->def = zlist;
964
1252
 
965
1253
    /* only allowed to request one list, if any */
966
1254
    list = nad_find_elem(pkt->nad, query, ns, "list", 1);
967
 
    if(list >= 0 && nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0) {
968
 
        /* hack the error in */
969
 
        pkt_error(pkt, stanza_err_BAD_REQUEST);
970
 
 
971
 
        pkt_sess(pkt, sess);
972
 
        return mod_HANDLED;
973
 
    }
 
1255
    if(list >= 0 && nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0)
 
1256
        return -stanza_err_BAD_REQUEST;
974
1257
 
975
1258
    result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);
976
1259
 
981
1264
 
982
1265
    /* just do one */
983
1266
    if(list >= 0) {
984
 
      name = nad_find_attr(pkt->nad, list, -1, "name", NULL);
985
 
 
986
 
      zlist = xhash_getx(z->lists, NAD_AVAL(pkt->nad, name), NAD_AVAL_L(pkt->nad, name));
987
 
      if(zlist == NULL) {
988
 
            /* hack the error in */
989
 
            pkt_error(pkt, stanza_err_ITEM_NOT_FOUND);
990
 
 
991
 
            pkt_sess(pkt, sess);
992
 
            return mod_HANDLED;
993
 
        }
 
1267
        name = nad_find_attr(pkt->nad, list, -1, "name", NULL);
 
1268
 
 
1269
        zlist = xhash_getx(z->lists, NAD_AVAL(pkt->nad, name), NAD_AVAL_L(pkt->nad, name));
 
1270
        if(zlist == NULL)
 
1271
            return -stanza_err_ITEM_NOT_FOUND;
994
1272
 
995
1273
        _privacy_result_builder(z->lists, zlist->name, (void *) zlist, (void *) result);
996
1274
    }
1003
1281
    /* tell them about current active and default list if they asked for everything */
1004
1282
    if(list < 0) {
1005
1283
        /* active */
1006
 
        if(sess->module_data[mod->index] != NULL) {
 
1284
        if(((privacy_t) sess->module_data[mod->index])->active != NULL) {
1007
1285
            active = nad_insert_elem(result->nad, query, ns, "active", NULL);
1008
 
            nad_set_attr(result->nad, active, -1, "name", ((zebra_list_t) sess->module_data[mod->index])->name, 0);
 
1286
            nad_set_attr(result->nad, active, -1, "name", ((privacy_t) sess->module_data[mod->index])->active->name, 0);
1009
1287
        }
1010
1288
 
1011
1289
        /* and the default list */
1032
1310
    storage_delete(mi->sm->st, "privacy-default", jid_user(jid), NULL);
1033
1311
}
1034
1312
 
1035
 
int privacy_init(mod_instance_t mi, char *arg) {
 
1313
static void _privacy_free(module_t mod) {
 
1314
     sm_unregister_ns(mod->mm->sm, uri_PRIVACY);
 
1315
     feature_unregister(mod->mm->sm, uri_PRIVACY);
 
1316
}
 
1317
 
 
1318
DLLEXPORT int module_init(mod_instance_t mi, char *arg) {
1036
1319
    module_t mod = mi->mod;
1037
1320
 
1038
 
    if(mod->init) return 0;
 
1321
    if (mod->init) return 0;
1039
1322
 
1040
1323
    mod->user_load = _privacy_user_load;
1041
1324
    mod->in_router = _privacy_in_router;
1042
1325
    mod->out_router = _privacy_out_router;
1043
1326
    mod->in_sess = _privacy_in_sess;
1044
1327
    mod->user_delete = _privacy_user_delete;
 
1328
    mod->free = _privacy_free;
1045
1329
 
 
1330
    ns_PRIVACY = sm_register_ns(mod->mm->sm, uri_PRIVACY);
1046
1331
    feature_register(mod->mm->sm, uri_PRIVACY);
 
1332
    ns_BLOCKING = sm_register_ns(mod->mm->sm, urn_BLOCKING);
 
1333
    feature_register(mod->mm->sm, urn_BLOCKING);
1047
1334
 
1048
1335
    return 0;
1049
1336
}