2 * Copyright (c) 2012, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include <trust_router/tr_name.h>
45 /* static prototypes */
46 static TR_NAME *tr_comm_memb_get_realm_id(TR_COMM_MEMB *memb);
49 static int tr_comm_destructor(void *obj)
51 TR_COMM *comm=talloc_get_type_abort(obj, TR_COMM);
53 tr_free_name(comm->id);
54 if (comm->owner_realm!=NULL)
55 tr_free_name(comm->owner_realm);
56 if (comm->owner_contact!=NULL)
57 tr_free_name(comm->owner_contact);
61 TR_COMM *tr_comm_new(TALLOC_CTX *mem_ctx)
63 TR_COMM *comm=talloc(mem_ctx, TR_COMM);
67 comm->type=TR_COMM_UNKNOWN;
69 comm->owner_realm=NULL;
70 comm->owner_contact=NULL;
71 comm->expiration_interval=0;
73 talloc_set_destructor((void *)comm, tr_comm_destructor);
78 void tr_comm_free(TR_COMM *comm)
83 void tr_comm_set_id(TR_COMM *comm, TR_NAME *id)
86 tr_free_name(comm->id);
90 void tr_comm_incref(TR_COMM *comm)
95 void tr_comm_decref(TR_COMM *comm)
101 TR_APC *tr_comm_get_apcs(TR_COMM *comm)
106 TR_NAME *tr_comm_get_id(TR_COMM *comm)
111 TR_NAME *tr_comm_dup_id(TR_COMM *comm)
113 return tr_dup_name(comm->id);
116 void tr_comm_set_type(TR_COMM *comm, TR_COMM_TYPE type)
121 TR_COMM_TYPE tr_comm_get_type(TR_COMM *comm)
126 void tr_comm_set_owner_realm(TR_COMM *comm, TR_NAME *realm)
128 if (comm->owner_realm!=NULL)
129 tr_free_name(comm->owner_realm);
130 comm->owner_realm=realm;
133 TR_NAME *tr_comm_get_owner_realm(TR_COMM *comm)
135 return comm->owner_realm;
138 TR_NAME *tr_comm_dup_owner_realm(TR_COMM *comm)
140 return tr_dup_name(comm->owner_realm);
143 void tr_comm_set_owner_contact(TR_COMM *comm, TR_NAME *contact)
145 if (comm->owner_contact != NULL)
146 tr_free_name(comm->owner_contact);
147 comm->owner_contact=contact;
150 TR_NAME *tr_comm_get_owner_contact(TR_COMM *comm)
152 return comm->owner_contact;
155 TR_NAME *tr_comm_dup_owner_contact(TR_COMM *comm)
157 return tr_dup_name(comm->owner_contact);
160 unsigned int tr_comm_get_refcount(TR_COMM *comm)
162 return comm->refcount;
165 /* add to the table if it's a new membership or has a shorter
166 * provenance list than our existing membership */
167 static void tr_comm_add_if_shorter(TR_COMM_TABLE *ctab, TR_COMM_MEMB *existing, TR_COMM_MEMB *newmemb)
169 if (existing==NULL) {
170 /* not in the table */
171 tr_comm_table_add_memb(ctab, newmemb);
173 /* Had an entry. Replace if we have shorter provenance. */
174 if (tr_comm_memb_provenance_len(newmemb) < tr_comm_memb_provenance_len(existing)) {
175 tr_comm_table_remove_memb(ctab, existing);
176 tr_comm_memb_free(existing);
177 tr_comm_table_add_memb(ctab, newmemb);
182 /* does not take responsibility for freeing IDP realm */
183 void tr_comm_add_idp_realm(TR_COMM_TABLE *ctab,
187 struct timespec *expiry)
189 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
190 TR_COMM_MEMB *newmemb=tr_comm_memb_new(tmp_ctx);
191 TR_COMM_MEMB *existing=NULL;
194 tr_err("tr_comm_add_idp_realm: unable to allocate new membership record.");
195 talloc_free(tmp_ctx);
199 tr_comm_memb_set_idp_realm(newmemb, realm);
200 tr_comm_memb_set_comm(newmemb, comm);
201 tr_comm_memb_set_provenance(newmemb, provenance);
202 tr_comm_memb_set_expiry(newmemb, expiry);
204 existing=tr_comm_table_find_idp_memb_origin(ctab,
205 tr_idp_realm_get_id(realm),
206 tr_comm_get_id(comm),
207 tr_comm_memb_get_origin(newmemb));
208 tr_comm_add_if_shorter(ctab, existing, newmemb); /* takes newmemb out of tmp_ctx if needed */
209 talloc_free(tmp_ctx);
212 /* does not take responsibility for freeing RP realm */
213 void tr_comm_add_rp_realm(TR_COMM_TABLE *ctab,
217 struct timespec *expiry)
219 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
220 TR_COMM_MEMB *newmemb=tr_comm_memb_new(tmp_ctx);
221 TR_COMM_MEMB *existing=NULL;
224 tr_err("tr_comm_add_idp_realm: unable to allocate new membership record.");
225 talloc_free(tmp_ctx);
229 tr_comm_memb_set_rp_realm(newmemb, realm);
230 tr_comm_memb_set_comm(newmemb, comm);
231 tr_comm_memb_set_provenance(newmemb, provenance);
232 tr_comm_memb_set_expiry(newmemb, expiry);
234 existing=tr_comm_table_find_rp_memb_origin(ctab,
235 tr_rp_realm_get_id(realm),
236 tr_comm_get_id(comm),
237 tr_comm_memb_get_origin(newmemb));
238 tr_comm_add_if_shorter(ctab, existing, newmemb); /* takes newmemb out of tmp_ctx if needed */
239 talloc_free(tmp_ctx);
242 static TR_COMM *tr_comm_tail(TR_COMM *comm)
247 while (comm->next!=NULL)
252 /* All list members are in the talloc context of the head.
253 * This will require careful thought if entries are ever removed
254 * Call like comms=tr_comm_add_func(comms, new_comm);
255 * or just use the tr_comm_add(comms, new) macro. */
256 #define tr_comm_add(comms, new) ((comms)=tr_comm_add_func((comms), (new)))
257 static TR_COMM *tr_comm_add_func(TR_COMM *comms, TR_COMM *new)
262 tr_comm_tail(comms)->next=new;
264 talloc_steal(comms, new);
271 /* guarantees comm is not in the list, not an error if it was't there */
272 #define tr_comm_remove(comms, c) ((comms)=tr_comm_remove_func((comms), (c)))
273 static TR_COMM *tr_comm_remove_func(TR_COMM *comms, TR_COMM *remove)
277 if ((this==NULL) || (this==remove))
280 for (; this->next!=NULL; this=this->next) {
281 if (this->next==remove)
282 this->next=remove->next;
287 TR_IDP_REALM *tr_comm_find_idp(TR_COMM_TABLE *ctab, TR_COMM *comm, TR_NAME *idp_realm)
289 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
290 TR_COMM_ITER *iter=NULL;
291 TR_IDP_REALM *this_idp=NULL;
293 if ((NULL==ctab) || (NULL==comm) || (NULL==idp_realm)) {
294 talloc_free(tmp_ctx);
298 iter=tr_comm_iter_new(tmp_ctx);
299 for (this_idp=tr_idp_realm_iter_first(iter, ctab, tr_comm_get_id(comm));
301 this_idp=tr_idp_realm_iter_next(iter)) {
302 if (0==tr_name_cmp(idp_realm, tr_idp_realm_get_id(this_idp))) {
303 tr_debug("tr_comm_find_idp: Found IdP %s in community %s.", idp_realm->buf, tr_comm_get_id(comm)->buf);
304 talloc_free(tmp_ctx);
308 tr_debug("tr_comm_find_idp: Unable to find IdP %s in community %s.", idp_realm->buf, tr_comm_get_id(comm)->buf);
309 talloc_free(tmp_ctx);
313 TR_RP_REALM *tr_comm_find_rp (TR_COMM_TABLE *ctab, TR_COMM *comm, TR_NAME *rp_realm)
315 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
316 TR_COMM_ITER *iter=NULL;
317 TR_RP_REALM *this_rp=NULL;
319 if ((NULL==ctab) || (NULL==comm) || (NULL==rp_realm)) {
320 talloc_free(tmp_ctx);
324 iter=tr_comm_iter_new(tmp_ctx);
325 for (this_rp=tr_rp_realm_iter_first(iter, ctab, tr_comm_get_id(comm));
327 this_rp=tr_rp_realm_iter_next(iter)) {
328 if (0==tr_name_cmp(rp_realm, tr_rp_realm_get_id(this_rp))) {
329 tr_debug("tr_comm_find_rp: Found RP %s in community %s.", rp_realm->buf, tr_comm_get_id(comm)->buf);
330 talloc_free(tmp_ctx);
334 tr_debug("tr_comm_find_rp: Unable to find RP %s in community %s.", rp_realm->buf, tr_comm_get_id(comm)->buf);
335 talloc_free(tmp_ctx);
339 static TR_COMM *tr_comm_lookup(TR_COMM *comms, TR_NAME *comm_name)
341 TR_COMM *cfg_comm = NULL;
343 for (cfg_comm = comms; NULL != cfg_comm; cfg_comm = cfg_comm->next) {
344 if (0==tr_name_cmp(cfg_comm->id, comm_name))
350 TR_COMM_ITER *tr_comm_iter_new(TALLOC_CTX *mem_ctx)
352 TR_COMM_ITER *iter=talloc(mem_ctx, TR_COMM_ITER);
362 void tr_comm_iter_free(TR_COMM_ITER *iter)
368 TR_COMM *tr_comm_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *realm)
372 /* find memberships for this realm */
373 for (iter->cur_memb=ctab->memberships;
374 iter->cur_memb!=NULL;
375 iter->cur_memb=iter->cur_memb->next) {
376 if (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb)))
377 return tr_comm_memb_get_comm(iter->cur_memb);
382 TR_COMM *tr_comm_iter_next(TR_COMM_ITER *iter)
384 for (iter->cur_memb=iter->cur_memb->next;
385 iter->cur_memb!=NULL;
386 iter->cur_memb=iter->cur_memb->next) {
387 if (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb)))
388 return tr_comm_memb_get_comm(iter->cur_memb);
393 /* iterate only over RPs */
394 TR_COMM *tr_comm_iter_first_rp(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *realm)
398 /* find memberships for this realm */
399 for (iter->cur_memb=ctab->memberships;
400 iter->cur_memb!=NULL;
401 iter->cur_memb=iter->cur_memb->next) {
402 if ((tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL) &&
403 (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb))))
404 return tr_comm_memb_get_comm(iter->cur_memb);
409 TR_COMM *tr_comm_iter_next_rp(TR_COMM_ITER *iter)
411 for (iter->cur_memb=iter->cur_memb->next;
412 iter->cur_memb!=NULL;
413 iter->cur_memb=iter->cur_memb->next) {
414 if ((tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL) &&
415 (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb))))
416 return tr_comm_memb_get_comm(iter->cur_memb);
421 /* iterate only over IDPs */
422 TR_COMM *tr_comm_iter_first_idp(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *realm)
426 /* find memberships for this realm */
427 for (iter->cur_memb=ctab->memberships;
428 iter->cur_memb!=NULL;
429 iter->cur_memb=iter->cur_memb->next) {
430 if ((tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL) &&
431 (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb))))
432 return tr_comm_memb_get_comm(iter->cur_memb);
437 TR_COMM *tr_comm_iter_next_idp(TR_COMM_ITER *iter)
439 for (iter->cur_memb=iter->cur_memb->next;
440 iter->cur_memb!=NULL;
441 iter->cur_memb=iter->cur_memb->next) {
442 if ((tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL) &&
443 (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb))))
444 return tr_comm_memb_get_comm(iter->cur_memb);
449 static TR_REALM *tr_realm_new(TALLOC_CTX *mem_ctx)
451 TR_REALM *realm=talloc(mem_ctx, TR_REALM);
453 realm->role=TR_ROLE_UNKNOWN;
460 static void tr_realm_free(TR_REALM *realm)
465 static void tr_realm_set_rp(TR_REALM *realm, TR_RP_REALM *rp)
467 if (realm->idp!=NULL)
469 realm->role=TR_ROLE_RP;
473 static void tr_realm_set_idp(TR_REALM *realm, TR_IDP_REALM *idp)
477 realm->role=TR_ROLE_IDP;
481 TR_NAME *tr_realm_get_id(TR_REALM *realm)
483 switch (realm->role) {
485 return tr_rp_realm_get_id(realm->rp);
487 return tr_idp_realm_get_id(realm->idp);
494 TR_NAME *tr_realm_dup_id(TR_REALM *realm)
496 return tr_dup_name(tr_realm_get_id(realm));
499 /* Iterate over either sort of realm. Do not free the TR_REALM returned. It becomes
500 * undefined/invalid after the next operation affecting the iterator. */
501 TR_REALM *tr_realm_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *comm)
504 if (iter->realm==NULL)
505 iter->realm=tr_realm_new(iter);
506 if (iter->realm==NULL)
509 /* find memberships for this comm */
510 for (iter->cur_memb=ctab->memberships;
511 iter->cur_memb!=NULL;
512 iter->cur_memb=iter->cur_memb->next) {
513 if (0==tr_name_cmp(iter->match,
514 tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))) {
515 /* found a match, determine whether it's an rp realm or an idp realm */
516 if (tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL)
517 tr_realm_set_rp(iter->realm, tr_comm_memb_get_rp_realm(iter->cur_memb));
518 else if (tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL)
519 tr_realm_set_idp(iter->realm, tr_comm_memb_get_idp_realm(iter->cur_memb));
521 if (iter->realm!=NULL)
522 tr_realm_free(iter->realm);
528 if (iter->realm!=NULL)
529 tr_realm_free(iter->realm);
534 TR_REALM *tr_realm_iter_next(TR_COMM_ITER *iter)
536 if (iter->realm==NULL)
539 /* find memberships for this comm */
540 for (iter->cur_memb=iter->cur_memb->next;
541 iter->cur_memb!=NULL;
542 iter->cur_memb=iter->cur_memb->next) {
543 if (0==tr_name_cmp(iter->match,
544 tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))) {
545 /* found a match, determine whether it's an rp realm or an idp realm */
546 if (tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL)
547 tr_realm_set_rp(iter->realm, tr_comm_memb_get_rp_realm(iter->cur_memb));
548 else if (tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL)
549 tr_realm_set_idp(iter->realm, tr_comm_memb_get_idp_realm(iter->cur_memb));
551 if (iter->realm!=NULL)
552 tr_realm_free(iter->realm);
558 if (iter->realm!=NULL)
559 tr_realm_free(iter->realm);
564 TR_RP_REALM *tr_rp_realm_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *comm)
568 /* find memberships for this comm */
569 for (iter->cur_memb=ctab->memberships;
570 iter->cur_memb!=NULL;
571 iter->cur_memb=iter->cur_memb->next) {
572 if ((tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL) &&
573 (0==tr_name_cmp(iter->match, tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))))
574 return tr_comm_memb_get_rp_realm(iter->cur_memb);
579 TR_RP_REALM *tr_rp_realm_iter_next(TR_COMM_ITER *iter)
581 for (iter->cur_memb=iter->cur_memb->next;
582 iter->cur_memb!=NULL;
583 iter->cur_memb=iter->cur_memb->next) {
584 if ((tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL) &&
585 (0==tr_name_cmp(iter->match, tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))))
586 return tr_comm_memb_get_rp_realm(iter->cur_memb);
591 TR_IDP_REALM *tr_idp_realm_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *comm)
595 /* find memberships for this comm */
596 for (iter->cur_memb=ctab->memberships;
597 iter->cur_memb!=NULL;
598 iter->cur_memb=iter->cur_memb->next) {
599 if ((tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL) &&
600 (0==tr_name_cmp(iter->match, tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))))
601 return tr_comm_memb_get_idp_realm(iter->cur_memb);
606 TR_IDP_REALM *tr_idp_realm_iter_next(TR_COMM_ITER *iter)
608 for (iter->cur_memb=iter->cur_memb->next;
609 iter->cur_memb!=NULL;
610 iter->cur_memb=iter->cur_memb->next) {
611 if ((tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL) &&
612 (0==tr_name_cmp(iter->match, tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))))
613 return tr_comm_memb_get_idp_realm(iter->cur_memb);
618 /* iterators for all communities in a table */
619 TR_COMM *tr_comm_table_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab)
621 iter->cur_comm=ctab->comms;
622 return iter->cur_comm;
625 TR_COMM *tr_comm_table_iter_next(TR_COMM_ITER *iter)
627 return iter->cur_comm=iter->cur_comm->next;
630 const char *tr_comm_type_to_str(TR_COMM_TYPE type)
634 case TR_COMM_UNKNOWN:
649 TR_COMM_MEMB *tr_comm_memb_iter_first(TR_COMM_ITER *iter, TR_COMM_MEMB *memb)
652 return iter->cur_memb;
655 TR_COMM_MEMB *tr_comm_memb_iter_next(TR_COMM_ITER *iter)
657 if (iter->cur_memb!=NULL)
658 iter->cur_memb=iter->cur_memb->origin_next;
659 return iter->cur_memb;
662 TR_COMM_TYPE tr_comm_type_from_str(const char *s)
664 if (strcmp(s, "apc")==0)
666 if (strcmp(s,"coi")==0)
668 return TR_COMM_UNKNOWN;
672 static int tr_comm_memb_destructor(void *obj)
674 TR_COMM_MEMB *memb=talloc_get_type_abort(obj, TR_COMM_MEMB);
675 if (memb->origin!=NULL)
676 tr_free_name(memb->origin);
679 tr_rp_realm_decref(memb->rp);
681 tr_idp_realm_decref(memb->idp);
682 if (memb->comm!=NULL)
683 tr_comm_decref(memb->comm);
684 if (memb->provenance!=NULL)
685 json_decref(memb->provenance);
689 TR_COMM_MEMB *tr_comm_memb_new(TALLOC_CTX *mem_ctx)
691 TR_COMM_MEMB *memb=talloc(mem_ctx, TR_COMM_MEMB);
694 memb->origin_next=NULL;
699 memb->provenance=NULL;
702 talloc_set_destructor(memb, tr_comm_memb_destructor);
707 void tr_comm_memb_free(TR_COMM_MEMB *memb)
712 TR_REALM_ROLE tr_comm_memb_get_role(TR_COMM_MEMB *memb)
718 return TR_ROLE_UNKNOWN;
721 void tr_comm_memb_set_rp_realm(TR_COMM_MEMB *memb, TR_RP_REALM *realm)
723 if (memb->idp!=NULL) {
724 tr_idp_realm_decref(memb->idp);
728 tr_rp_realm_decref(memb->rp);
732 tr_rp_realm_incref(realm);
735 TR_RP_REALM *tr_comm_memb_get_rp_realm(TR_COMM_MEMB *memb)
740 void tr_comm_memb_set_idp_realm(TR_COMM_MEMB *memb, TR_IDP_REALM *realm)
742 if (memb->rp!=NULL) {
743 tr_rp_realm_decref(memb->rp);
747 tr_idp_realm_decref(memb->idp);
750 tr_idp_realm_incref(realm);
753 TR_IDP_REALM *tr_comm_memb_get_idp_realm(TR_COMM_MEMB *memb)
758 void tr_comm_memb_set_comm(TR_COMM_MEMB *memb, TR_COMM *comm)
760 if (memb->comm!=NULL)
761 tr_comm_decref(memb->comm);
763 tr_comm_incref(comm);
766 TR_COMM *tr_comm_memb_get_comm(TR_COMM_MEMB *memb)
771 static void tr_comm_memb_set_origin(TR_COMM_MEMB *memb, TR_NAME *origin)
773 if (memb->origin!=NULL)
774 tr_free_name(memb->origin);
778 TR_NAME *tr_comm_memb_get_origin(TR_COMM_MEMB *memb)
783 TR_NAME *tr_comm_memb_dup_origin(TR_COMM_MEMB *memb)
785 if (memb->origin!=NULL)
786 return tr_dup_name(memb->origin);
790 json_t *tr_comm_memb_get_provenance(TR_COMM_MEMB *memb)
793 return memb->provenance;
797 void tr_comm_memb_set_provenance(TR_COMM_MEMB *memb, json_t *prov)
799 if (memb->provenance)
800 json_decref(memb->provenance);
802 memb->provenance=prov;
806 /* next line sets origin to NULL if provenance is empty because jansson
807 * routines return NULL on error */
808 memb->origin=tr_new_name(json_string_value(json_array_get(prov, 0)));
810 tr_comm_memb_set_origin(memb, NULL);
814 void tr_comm_memb_add_to_provenance(TR_COMM_MEMB *memb, TR_NAME *hop)
816 if (memb->provenance==NULL) {
817 memb->provenance=json_array();
818 if (memb->provenance==NULL) {
819 tr_err("tr_comm_memb_add_to_provenance: unable to allocate provenance list.");
822 /* this is the first entry in the provenance, so it is the origin */
823 tr_comm_memb_set_origin(memb,tr_dup_name(hop));
824 if (memb->origin==NULL) {
825 tr_err("tr_comm_memb_add_to_provenance: unable to allocate origin.");
826 json_decref(memb->provenance);
827 memb->provenance=NULL;
831 if (0!=json_array_append_new(memb->provenance, tr_name_to_json_string(hop)))
832 tr_err("tr_comm_memb_add_to_provenance: unable to extend provenance list.");
835 size_t tr_comm_memb_provenance_len(TR_COMM_MEMB *memb)
837 if (memb->provenance==NULL)
839 return json_array_size(memb->provenance);
842 void tr_comm_memb_set_interval(TR_COMM_MEMB *memb, unsigned int interval)
844 memb->interval=interval;
847 unsigned int tr_comm_memb_get_interval(TR_COMM_MEMB *memb)
849 return memb->interval;
852 void tr_comm_memb_set_expiry(TR_COMM_MEMB *memb, struct timespec *time)
857 struct timespec *tr_comm_memb_get_expiry(TR_COMM_MEMB *memb)
862 int tr_comm_memb_is_expired(TR_COMM_MEMB *memb, struct timespec *curtime)
864 return ((curtime->tv_sec > memb->expiry->tv_sec)
865 || ((curtime->tv_sec == memb->expiry->tv_sec)
866 &&(curtime->tv_nsec >= memb->expiry->tv_nsec)));
869 TR_COMM_TABLE *tr_comm_table_new(TALLOC_CTX *mem_ctx)
871 TR_COMM_TABLE *ctab=talloc(mem_ctx, TR_COMM_TABLE);
874 ctab->memberships=NULL;
879 void tr_comm_table_free(TR_COMM_TABLE *ctab)
884 static TR_REALM_ROLE tr_comm_memb_role(TR_COMM_MEMB *memb)
891 return TR_ROLE_UNKNOWN;
894 void tr_comm_table_add_memb(TR_COMM_TABLE *ctab, TR_COMM_MEMB *new)
896 TR_COMM_MEMB *cur=NULL;
898 /* handle the empty list case */
899 if (ctab->memberships==NULL) {
900 ctab->memberships=new;
901 talloc_steal(ctab, new);
905 /* The list was not empty. See if we already have a membership for this realm/comm/role */
906 switch (tr_comm_memb_role(new)) {
908 cur=tr_comm_table_find_rp_memb(ctab,
909 tr_rp_realm_get_id(tr_comm_memb_get_rp_realm(new)),
910 tr_comm_get_id(tr_comm_memb_get_comm(new)));
913 cur=tr_comm_table_find_idp_memb(ctab,
914 tr_idp_realm_get_id(tr_comm_memb_get_idp_realm(new)),
915 tr_comm_get_id(tr_comm_memb_get_comm(new)));
917 case TR_ROLE_UNKNOWN:
919 tr_err("tr_comm_table_add_memb: realm with unknown role added.");
924 /* no entry for this realm/comm/role, tack it on the end */
925 for (cur=ctab->memberships; cur->next!=NULL; cur=cur->next) { }
928 /* Found an entry. Add to the end of its same-origin list. */
929 while (cur->origin_next!=NULL) {
930 cur=cur->origin_next;
932 cur->origin_next=new;
935 talloc_steal(ctab, new);
938 /* Remove memb from ctab. Do not free anything. Do nothing if memb not in ctab. */
939 void tr_comm_table_remove_memb(TR_COMM_TABLE *ctab, TR_COMM_MEMB *memb)
941 TR_COMM_MEMB *cur=NULL; /* for walking the main list */
942 TR_COMM_MEMB *orig_cur=NULL; /* for walking the origin list */
944 if ((memb==NULL) || (ctab->memberships==NULL))
947 /* see if it's the first member */
948 if (ctab->memberships==memb) {
949 if (memb->origin_next!=NULL) {
950 memb->origin_next->next=ctab->memberships->next;
951 ctab->memberships=memb->origin_next;
953 ctab->memberships=memb->next;
958 /* see if it's in first member's origin list */
959 for (orig_cur=ctab->memberships->origin_next;
961 orig_cur=ctab->memberships->origin_next) {
962 if (orig_cur==memb) {
963 orig_cur->origin_next=memb->origin_next;
968 /* now we have to walk the rest of the tree */
969 for (cur=ctab->memberships; cur->next!=NULL; cur=cur->next) {
970 if (cur->next==memb) {
971 /* it matched an entry on the main list */
972 if (memb->origin_next!=NULL) {
973 /* replace the entry in the main list with the next element on the origin list */
974 memb->origin_next->next=memb->next;
975 cur->next=memb->origin_next;
977 cur->next=memb->next; /* no origin list, just drop memb */
980 /* it was not on the main list, walk the origin list */
981 for (orig_cur=cur; orig_cur->next!=NULL; orig_cur=orig_cur->next) {
982 if (orig_cur->next==memb) {
983 orig_cur->next=memb->next;
984 return; /* just drop the element from the origin list */
991 static TR_NAME *tr_comm_memb_get_realm_id(TR_COMM_MEMB *memb)
994 return tr_rp_realm_get_id(memb->rp);
996 return tr_idp_realm_get_id(memb->idp);
999 /* find a membership from any origin */
1000 TR_COMM_MEMB *tr_comm_table_find_memb(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm)
1002 TR_COMM_MEMB *cur=NULL;
1003 TR_NAME *cur_realm_name=NULL;
1005 for (cur=ctab->memberships; cur!=NULL; cur=cur->next) {
1006 cur_realm_name=tr_comm_memb_get_realm_id(cur);
1007 if (cur_realm_name==NULL) {
1008 tr_warning("tr_comm_table_find: encountered realm with no name.");
1011 if ((0==tr_name_cmp(realm, cur_realm_name)) &&
1012 (0==tr_name_cmp(comm, tr_comm_get_id(tr_comm_memb_get_comm(cur))))) {
1019 /* find a membership from a particular origin */
1020 TR_COMM_MEMB *tr_comm_table_find_memb_origin(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm, TR_NAME *origin)
1022 TR_NAME *cur_orig=NULL;
1023 TR_COMM_MEMB *cur=tr_comm_table_find_memb(ctab, realm, comm);
1025 return NULL; /* no match */
1027 /* had a match for comm/realm; find origin match */
1029 if (((origin==NULL) && (cur_orig==NULL)) ||
1030 ((origin!=NULL) && (cur_orig!=NULL) && (0==tr_name_cmp(origin, cur_orig))))
1031 return cur; /* found a match */
1032 cur=cur->origin_next;
1034 return NULL; /* no match */
1038 /* find an idp membership regardless of its origin */
1039 TR_COMM_MEMB *tr_comm_table_find_idp_memb(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm)
1041 TR_COMM_MEMB *cur=NULL;
1042 TR_IDP_REALM *idp_realm=NULL;
1044 for (cur=ctab->memberships; cur!=NULL; cur=cur->next) {
1045 idp_realm=tr_comm_memb_get_idp_realm(cur);
1046 if (idp_realm==NULL)
1047 continue; /* was not an idp */
1049 if ((0==tr_name_cmp(realm, idp_realm->realm_id)) &&
1050 (0==tr_name_cmp(comm, tr_comm_get_id(tr_comm_memb_get_comm(cur))))) {
1057 /* find an idp membership from a particular origin */
1058 TR_COMM_MEMB *tr_comm_table_find_idp_memb_origin(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm, TR_NAME *origin)
1060 TR_NAME *cur_orig=NULL;
1061 TR_COMM_MEMB *cur=tr_comm_table_find_idp_memb(ctab, realm, comm);
1063 return NULL; /* no match */
1065 /* had a match for comm/realm; find origin match */
1067 cur_orig=tr_comm_memb_get_origin(cur);
1068 if (((origin==NULL) && (cur_orig==NULL)) ||
1069 ((origin!=NULL) && (cur_orig!=NULL) && (0==tr_name_cmp(origin, cur_orig))))
1070 return cur; /* found a match */
1071 cur=cur->origin_next;
1073 return NULL; /* no match */
1076 /* find an rp membership from any origin */
1077 TR_COMM_MEMB *tr_comm_table_find_rp_memb(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm)
1079 TR_COMM_MEMB *cur=NULL;
1080 TR_RP_REALM *rp_realm=NULL;
1082 for (cur=ctab->memberships; cur!=NULL; cur=cur->next) {
1083 rp_realm=tr_comm_memb_get_rp_realm(cur);
1085 continue; /* was not an rp */
1087 if ((0==tr_name_cmp(realm, tr_rp_realm_get_id(rp_realm))) &&
1088 (0==tr_name_cmp(comm, tr_comm_get_id(tr_comm_memb_get_comm(cur))))) {
1095 /* find an rp membership from a particular origin */
1096 TR_COMM_MEMB *tr_comm_table_find_rp_memb_origin(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm, TR_NAME *origin)
1098 TR_NAME *cur_orig=NULL;
1099 TR_COMM_MEMB *cur=tr_comm_table_find_rp_memb(ctab, realm, comm);
1101 return NULL; /* no match */
1103 /* had a match for comm/realm; find origin match */
1105 cur_orig=tr_comm_memb_get_origin(cur);
1106 if (((origin==NULL) && (cur_orig==NULL)) ||
1107 ((origin!=NULL) && (cur_orig!=NULL) && (0==tr_name_cmp(origin, cur_orig))))
1108 return cur; /* found a match */
1109 cur=cur->origin_next;
1111 return NULL; /* no match */
1114 TR_COMM *tr_comm_table_find_comm(TR_COMM_TABLE *ctab, TR_NAME *comm_id)
1116 return tr_comm_lookup(ctab->comms, comm_id);
1119 void tr_comm_table_add_comm(TR_COMM_TABLE *ctab, TR_COMM *new)
1121 tr_comm_add(ctab->comms, new);
1124 void tr_comm_table_remove_comm(TR_COMM_TABLE *ctab, TR_COMM *comm)
1126 tr_comm_remove(ctab->comms, comm);
1129 /* how many communities in the table? */
1130 size_t tr_comm_table_size(TR_COMM_TABLE *ctab)
1133 TR_COMM *this=ctab->comms;
1142 const char *tr_realm_role_to_str(TR_REALM_ROLE role)
1154 TR_REALM_ROLE tr_realm_role_from_str(const char *s)
1156 if (strcmp(s, "idp")==0)
1158 if (strcmp(s, "rp")==0)
1160 return TR_ROLE_UNKNOWN;