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.
41 #include <trust_router/tr_name.h>
46 /* static prototypes */
47 static TR_NAME *tr_comm_memb_get_realm_id(TR_COMM_MEMB *memb);
50 static int tr_comm_destructor(void *obj)
52 TR_COMM *comm=talloc_get_type_abort(obj, TR_COMM);
54 tr_free_name(comm->id);
55 if (comm->owner_realm!=NULL)
56 tr_free_name(comm->owner_realm);
57 if (comm->owner_contact!=NULL)
58 tr_free_name(comm->owner_contact);
62 TR_COMM *tr_comm_new(TALLOC_CTX *mem_ctx)
64 TR_COMM *comm=talloc(mem_ctx, TR_COMM);
68 comm->type=TR_COMM_UNKNOWN;
70 comm->owner_realm=NULL;
71 comm->owner_contact=NULL;
72 comm->expiration_interval=0;
74 talloc_set_destructor((void *)comm, tr_comm_destructor);
79 void tr_comm_free(TR_COMM *comm)
84 void tr_comm_set_id(TR_COMM *comm, TR_NAME *id)
87 tr_free_name(comm->id);
91 void tr_comm_incref(TR_COMM *comm)
96 void tr_comm_decref(TR_COMM *comm)
102 void tr_comm_set_apcs(TR_COMM *comm, TR_APC *apc)
104 if (comm->apcs!=NULL)
105 tr_apc_free(comm->apcs);
107 talloc_steal(comm, apc);
110 TR_APC *tr_comm_get_apcs(TR_COMM *comm)
115 TR_NAME *tr_comm_get_id(TR_COMM *comm)
120 TR_NAME *tr_comm_dup_id(TR_COMM *comm)
122 return tr_dup_name(comm->id);
125 void tr_comm_set_type(TR_COMM *comm, TR_COMM_TYPE type)
130 TR_COMM_TYPE tr_comm_get_type(TR_COMM *comm)
135 void tr_comm_set_owner_realm(TR_COMM *comm, TR_NAME *realm)
137 if (comm->owner_realm!=NULL)
138 tr_free_name(comm->owner_realm);
139 comm->owner_realm=realm;
142 TR_NAME *tr_comm_get_owner_realm(TR_COMM *comm)
144 return comm->owner_realm;
147 TR_NAME *tr_comm_dup_owner_realm(TR_COMM *comm)
149 return tr_dup_name(comm->owner_realm);
152 void tr_comm_set_owner_contact(TR_COMM *comm, TR_NAME *contact)
154 if (comm->owner_contact != NULL)
155 tr_free_name(comm->owner_contact);
156 comm->owner_contact=contact;
159 TR_NAME *tr_comm_get_owner_contact(TR_COMM *comm)
161 return comm->owner_contact;
164 TR_NAME *tr_comm_dup_owner_contact(TR_COMM *comm)
166 return tr_dup_name(comm->owner_contact);
169 unsigned int tr_comm_get_refcount(TR_COMM *comm)
171 return comm->refcount;
174 /* add to the table if it's a new membership or has a shorter
175 * provenance list than our existing membership */
176 static void tr_comm_add_if_shorter(TR_COMM_TABLE *ctab, TR_COMM_MEMB *existing, TR_COMM_MEMB *newmemb)
178 if (existing==NULL) {
179 /* not in the table */
180 tr_comm_table_add_memb(ctab, newmemb);
182 /* Had an entry. Replace if we have shorter provenance. */
183 if (tr_comm_memb_provenance_len(newmemb) < tr_comm_memb_provenance_len(existing)) {
184 tr_comm_table_remove_memb(ctab, existing);
185 tr_comm_memb_free(existing);
186 tr_comm_table_add_memb(ctab, newmemb);
191 /* does not take responsibility for freeing IDP realm */
192 void tr_comm_add_idp_realm(TR_COMM_TABLE *ctab,
196 struct timespec *expiry)
198 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
199 TR_COMM_MEMB *newmemb=tr_comm_memb_new(tmp_ctx);
200 TR_COMM_MEMB *existing=NULL;
203 tr_err("tr_comm_add_idp_realm: unable to allocate new membership record.");
204 talloc_free(tmp_ctx);
208 tr_comm_memb_set_idp_realm(newmemb, realm);
209 tr_comm_memb_set_comm(newmemb, comm);
210 tr_comm_memb_set_provenance(newmemb, provenance);
211 tr_comm_memb_set_expiry(newmemb, expiry);
213 existing=tr_comm_table_find_idp_memb_origin(ctab,
214 tr_idp_realm_get_id(realm),
215 tr_comm_get_id(comm),
216 tr_comm_memb_get_origin(newmemb));
217 tr_comm_add_if_shorter(ctab, existing, newmemb); /* takes newmemb out of tmp_ctx if needed */
218 talloc_free(tmp_ctx);
221 /* does not take responsibility for freeing RP realm */
222 void tr_comm_add_rp_realm(TR_COMM_TABLE *ctab,
226 struct timespec *expiry)
228 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
229 TR_COMM_MEMB *newmemb=tr_comm_memb_new(tmp_ctx);
230 TR_COMM_MEMB *existing=NULL;
233 tr_err("tr_comm_add_idp_realm: unable to allocate new membership record.");
234 talloc_free(tmp_ctx);
238 tr_comm_memb_set_rp_realm(newmemb, realm);
239 tr_comm_memb_set_comm(newmemb, comm);
240 tr_comm_memb_set_provenance(newmemb, provenance);
241 tr_comm_memb_set_expiry(newmemb, expiry);
243 existing=tr_comm_table_find_rp_memb_origin(ctab,
244 tr_rp_realm_get_id(realm),
245 tr_comm_get_id(comm),
246 tr_comm_memb_get_origin(newmemb));
247 tr_comm_add_if_shorter(ctab, existing, newmemb); /* takes newmemb out of tmp_ctx if needed */
248 talloc_free(tmp_ctx);
251 static TR_COMM *tr_comm_tail(TR_COMM *comm)
256 while (comm->next!=NULL)
261 /* All list members are in the talloc context of the head.
262 * This will require careful thought if entries are ever removed
263 * Call like comms=tr_comm_add_func(comms, new_comm);
264 * or just use the tr_comm_add(comms, new) macro. */
265 #define tr_comm_add(comms, new) ((comms)=tr_comm_add_func((comms), (new)))
266 static TR_COMM *tr_comm_add_func(TR_COMM *comms, TR_COMM *new)
271 tr_comm_tail(comms)->next=new;
273 talloc_steal(comms, new);
280 /* Guarantees comm is not in the list, not an error if it was't there.
281 * Does not free the removed element, nor change its talloc context. */
282 #define tr_comm_remove(comms, c) ((comms)=tr_comm_remove_func((comms), (c)))
283 static TR_COMM *tr_comm_remove_func(TR_COMM *comms, TR_COMM *remove)
285 TALLOC_CTX *list_ctx=talloc_parent(comms); /* in case we need to remove the head */
292 /* if we're removing the head, put the next element (if present) into the context
293 * the list head was in. */
296 talloc_steal(list_ctx, comms->next);
297 /* now put all the other elements in the context of the list head */
298 for (this=comms->next; this!=NULL; this=this->next)
299 talloc_steal(comms, this);
302 /* not removing the head; no need to play with contexts */
303 for (this=comms; this->next!=NULL; this=this->next) {
304 if (this->next==remove)
305 this->next=remove->next;
311 TR_IDP_REALM *tr_comm_find_idp(TR_COMM_TABLE *ctab, TR_COMM *comm, TR_NAME *idp_realm)
313 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
314 TR_COMM_ITER *iter=NULL;
315 TR_IDP_REALM *this_idp=NULL;
317 if ((NULL==ctab) || (NULL==comm) || (NULL==idp_realm)) {
318 talloc_free(tmp_ctx);
322 iter=tr_comm_iter_new(tmp_ctx);
323 for (this_idp=tr_idp_realm_iter_first(iter, ctab, tr_comm_get_id(comm));
325 this_idp=tr_idp_realm_iter_next(iter)) {
326 if (0==tr_name_cmp(idp_realm, tr_idp_realm_get_id(this_idp))) {
327 tr_debug("tr_comm_find_idp: Found IdP %s in community %s.", idp_realm->buf, tr_comm_get_id(comm)->buf);
328 talloc_free(tmp_ctx);
332 tr_debug("tr_comm_find_idp: Unable to find IdP %s in community %s.", idp_realm->buf, tr_comm_get_id(comm)->buf);
333 talloc_free(tmp_ctx);
337 TR_RP_REALM *tr_comm_find_rp (TR_COMM_TABLE *ctab, TR_COMM *comm, TR_NAME *rp_realm)
339 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
340 TR_COMM_ITER *iter=NULL;
341 TR_RP_REALM *this_rp=NULL;
343 if ((NULL==ctab) || (NULL==comm) || (NULL==rp_realm)) {
344 talloc_free(tmp_ctx);
348 iter=tr_comm_iter_new(tmp_ctx);
349 for (this_rp=tr_rp_realm_iter_first(iter, ctab, tr_comm_get_id(comm));
351 this_rp=tr_rp_realm_iter_next(iter)) {
352 if (0==tr_name_cmp(rp_realm, tr_rp_realm_get_id(this_rp))) {
353 tr_debug("tr_comm_find_rp: Found RP %s in community %s.", rp_realm->buf, tr_comm_get_id(comm)->buf);
354 talloc_free(tmp_ctx);
358 tr_debug("tr_comm_find_rp: Unable to find RP %s in community %s.", rp_realm->buf, tr_comm_get_id(comm)->buf);
359 talloc_free(tmp_ctx);
363 static TR_COMM *tr_comm_lookup(TR_COMM *comms, TR_NAME *comm_name)
365 TR_COMM *cfg_comm = NULL;
367 for (cfg_comm = comms; NULL != cfg_comm; cfg_comm = cfg_comm->next) {
368 if (0==tr_name_cmp(cfg_comm->id, comm_name))
374 TR_COMM_ITER *tr_comm_iter_new(TALLOC_CTX *mem_ctx)
376 TR_COMM_ITER *iter=talloc(mem_ctx, TR_COMM_ITER);
386 void tr_comm_iter_free(TR_COMM_ITER *iter)
392 TR_COMM *tr_comm_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *realm)
396 /* find memberships for this realm */
397 for (iter->cur_memb=ctab->memberships;
398 iter->cur_memb!=NULL;
399 iter->cur_memb=iter->cur_memb->next) {
400 if (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb)))
401 return tr_comm_memb_get_comm(iter->cur_memb);
406 TR_COMM *tr_comm_iter_next(TR_COMM_ITER *iter)
408 for (iter->cur_memb=iter->cur_memb->next;
409 iter->cur_memb!=NULL;
410 iter->cur_memb=iter->cur_memb->next) {
411 if (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb)))
412 return tr_comm_memb_get_comm(iter->cur_memb);
417 /* iterate only over RPs */
418 TR_COMM *tr_comm_iter_first_rp(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *realm)
422 /* find memberships for this realm */
423 for (iter->cur_memb=ctab->memberships;
424 iter->cur_memb!=NULL;
425 iter->cur_memb=iter->cur_memb->next) {
426 if ((tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL) &&
427 (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb))))
428 return tr_comm_memb_get_comm(iter->cur_memb);
433 TR_COMM *tr_comm_iter_next_rp(TR_COMM_ITER *iter)
435 for (iter->cur_memb=iter->cur_memb->next;
436 iter->cur_memb!=NULL;
437 iter->cur_memb=iter->cur_memb->next) {
438 if ((tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL) &&
439 (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb))))
440 return tr_comm_memb_get_comm(iter->cur_memb);
445 /* iterate only over IDPs */
446 TR_COMM *tr_comm_iter_first_idp(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *realm)
450 /* find memberships for this realm */
451 for (iter->cur_memb=ctab->memberships;
452 iter->cur_memb!=NULL;
453 iter->cur_memb=iter->cur_memb->next) {
454 if ((tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL) &&
455 (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb))))
456 return tr_comm_memb_get_comm(iter->cur_memb);
461 TR_COMM *tr_comm_iter_next_idp(TR_COMM_ITER *iter)
463 for (iter->cur_memb=iter->cur_memb->next;
464 iter->cur_memb!=NULL;
465 iter->cur_memb=iter->cur_memb->next) {
466 if ((tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL) &&
467 (0==tr_name_cmp(iter->match, tr_comm_memb_get_realm_id(iter->cur_memb))))
468 return tr_comm_memb_get_comm(iter->cur_memb);
473 static TR_REALM *tr_realm_new(TALLOC_CTX *mem_ctx)
475 TR_REALM *realm=talloc(mem_ctx, TR_REALM);
477 realm->role=TR_ROLE_UNKNOWN;
484 static void tr_realm_free(TR_REALM *realm)
489 static void tr_realm_set_rp(TR_REALM *realm, TR_RP_REALM *rp)
491 if (realm->idp!=NULL)
493 realm->role=TR_ROLE_RP;
497 static void tr_realm_set_idp(TR_REALM *realm, TR_IDP_REALM *idp)
501 realm->role=TR_ROLE_IDP;
505 TR_NAME *tr_realm_get_id(TR_REALM *realm)
507 switch (realm->role) {
509 return tr_rp_realm_get_id(realm->rp);
511 return tr_idp_realm_get_id(realm->idp);
518 TR_NAME *tr_realm_dup_id(TR_REALM *realm)
520 return tr_dup_name(tr_realm_get_id(realm));
523 /* Iterate over either sort of realm. Do not free the TR_REALM returned. It becomes
524 * undefined/invalid after the next operation affecting the iterator. */
525 TR_REALM *tr_realm_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *comm)
528 if (iter->realm==NULL)
529 iter->realm=tr_realm_new(iter);
530 if (iter->realm==NULL)
533 /* find memberships for this comm */
534 for (iter->cur_memb=ctab->memberships;
535 iter->cur_memb!=NULL;
536 iter->cur_memb=iter->cur_memb->next) {
537 if (0==tr_name_cmp(iter->match,
538 tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))) {
539 /* found a match, determine whether it's an rp realm or an idp realm */
540 if (tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL)
541 tr_realm_set_rp(iter->realm, tr_comm_memb_get_rp_realm(iter->cur_memb));
542 else if (tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL)
543 tr_realm_set_idp(iter->realm, tr_comm_memb_get_idp_realm(iter->cur_memb));
545 if (iter->realm!=NULL)
546 tr_realm_free(iter->realm);
552 if (iter->realm!=NULL)
553 tr_realm_free(iter->realm);
558 TR_REALM *tr_realm_iter_next(TR_COMM_ITER *iter)
560 if (iter->realm==NULL)
563 /* find memberships for this comm */
564 for (iter->cur_memb=iter->cur_memb->next;
565 iter->cur_memb!=NULL;
566 iter->cur_memb=iter->cur_memb->next) {
567 if (0==tr_name_cmp(iter->match,
568 tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))) {
569 /* found a match, determine whether it's an rp realm or an idp realm */
570 if (tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL)
571 tr_realm_set_rp(iter->realm, tr_comm_memb_get_rp_realm(iter->cur_memb));
572 else if (tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL)
573 tr_realm_set_idp(iter->realm, tr_comm_memb_get_idp_realm(iter->cur_memb));
575 if (iter->realm!=NULL)
576 tr_realm_free(iter->realm);
582 if (iter->realm!=NULL)
583 tr_realm_free(iter->realm);
588 TR_RP_REALM *tr_rp_realm_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *comm)
592 /* find memberships for this comm */
593 for (iter->cur_memb=ctab->memberships;
594 iter->cur_memb!=NULL;
595 iter->cur_memb=iter->cur_memb->next) {
596 if ((tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL) &&
597 (0==tr_name_cmp(iter->match, tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))))
598 return tr_comm_memb_get_rp_realm(iter->cur_memb);
603 TR_RP_REALM *tr_rp_realm_iter_next(TR_COMM_ITER *iter)
605 for (iter->cur_memb=iter->cur_memb->next;
606 iter->cur_memb!=NULL;
607 iter->cur_memb=iter->cur_memb->next) {
608 if ((tr_comm_memb_get_rp_realm(iter->cur_memb)!=NULL) &&
609 (0==tr_name_cmp(iter->match, tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))))
610 return tr_comm_memb_get_rp_realm(iter->cur_memb);
615 TR_IDP_REALM *tr_idp_realm_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab, TR_NAME *comm)
619 /* find memberships for this comm */
620 for (iter->cur_memb=ctab->memberships;
621 iter->cur_memb!=NULL;
622 iter->cur_memb=iter->cur_memb->next) {
623 if ((tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL) &&
624 (0==tr_name_cmp(iter->match, tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))))
625 return tr_comm_memb_get_idp_realm(iter->cur_memb);
630 TR_IDP_REALM *tr_idp_realm_iter_next(TR_COMM_ITER *iter)
632 for (iter->cur_memb=iter->cur_memb->next;
633 iter->cur_memb!=NULL;
634 iter->cur_memb=iter->cur_memb->next) {
635 if ((tr_comm_memb_get_idp_realm(iter->cur_memb)!=NULL) &&
636 (0==tr_name_cmp(iter->match, tr_comm_get_id(tr_comm_memb_get_comm(iter->cur_memb)))))
637 return tr_comm_memb_get_idp_realm(iter->cur_memb);
642 /* iterators for all communities in a table */
643 TR_COMM *tr_comm_table_iter_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab)
645 iter->cur_comm=ctab->comms;
646 return iter->cur_comm;
649 TR_COMM *tr_comm_table_iter_next(TR_COMM_ITER *iter)
651 return iter->cur_comm=iter->cur_comm->next;
654 const char *tr_comm_type_to_str(TR_COMM_TYPE type)
658 case TR_COMM_UNKNOWN:
673 TR_COMM_MEMB *tr_comm_memb_iter_first(TR_COMM_ITER *iter, TR_COMM_MEMB *memb)
676 return iter->cur_memb;
679 TR_COMM_MEMB *tr_comm_memb_iter_next(TR_COMM_ITER *iter)
681 if (iter->cur_memb!=NULL)
682 iter->cur_memb=iter->cur_memb->origin_next;
683 return iter->cur_memb;
686 TR_COMM_TYPE tr_comm_type_from_str(const char *s)
688 if (strcmp(s, "apc")==0)
690 if (strcmp(s,"coi")==0)
692 return TR_COMM_UNKNOWN;
696 static int tr_comm_memb_destructor(void *obj)
698 TR_COMM_MEMB *memb=talloc_get_type_abort(obj, TR_COMM_MEMB);
699 if (memb->origin!=NULL)
700 tr_free_name(memb->origin);
703 tr_rp_realm_decref(memb->rp);
705 tr_idp_realm_decref(memb->idp);
706 if (memb->comm!=NULL)
707 tr_comm_decref(memb->comm);
708 if (memb->provenance!=NULL)
709 json_decref(memb->provenance);
713 TR_COMM_MEMB *tr_comm_memb_new(TALLOC_CTX *mem_ctx)
715 TR_COMM_MEMB *memb=talloc(mem_ctx, TR_COMM_MEMB);
718 memb->origin_next=NULL;
723 memb->provenance=NULL;
725 memb->expiry=talloc(memb, struct timespec);
726 if (memb->expiry==NULL) {
730 *(memb->expiry)=(struct timespec){0,0};
731 talloc_set_destructor(memb, tr_comm_memb_destructor);
736 void tr_comm_memb_free(TR_COMM_MEMB *memb)
741 TR_REALM_ROLE tr_comm_memb_get_role(TR_COMM_MEMB *memb)
747 return TR_ROLE_UNKNOWN;
750 void tr_comm_memb_set_rp_realm(TR_COMM_MEMB *memb, TR_RP_REALM *realm)
752 if (memb->idp!=NULL) {
753 tr_idp_realm_decref(memb->idp);
757 tr_rp_realm_decref(memb->rp);
761 tr_rp_realm_incref(realm);
764 TR_RP_REALM *tr_comm_memb_get_rp_realm(TR_COMM_MEMB *memb)
769 void tr_comm_memb_set_idp_realm(TR_COMM_MEMB *memb, TR_IDP_REALM *realm)
771 if (memb->rp!=NULL) {
772 tr_rp_realm_decref(memb->rp);
776 tr_idp_realm_decref(memb->idp);
779 tr_idp_realm_incref(realm);
782 TR_IDP_REALM *tr_comm_memb_get_idp_realm(TR_COMM_MEMB *memb)
787 void tr_comm_memb_set_comm(TR_COMM_MEMB *memb, TR_COMM *comm)
789 if (memb->comm!=NULL)
790 tr_comm_decref(memb->comm);
792 tr_comm_incref(comm);
795 TR_COMM *tr_comm_memb_get_comm(TR_COMM_MEMB *memb)
800 static void tr_comm_memb_set_origin(TR_COMM_MEMB *memb, TR_NAME *origin)
802 if (memb->origin!=NULL)
803 tr_free_name(memb->origin);
807 TR_NAME *tr_comm_memb_get_origin(TR_COMM_MEMB *memb)
812 TR_NAME *tr_comm_memb_dup_origin(TR_COMM_MEMB *memb)
814 if (memb->origin!=NULL)
815 return tr_dup_name(memb->origin);
819 json_t *tr_comm_memb_get_provenance(TR_COMM_MEMB *memb)
822 return memb->provenance;
826 void tr_comm_memb_set_provenance(TR_COMM_MEMB *memb, json_t *prov)
828 if (memb->provenance)
829 json_decref(memb->provenance);
831 memb->provenance=prov;
835 /* next line sets origin to NULL if provenance is empty because jansson
836 * routines return NULL on error */
837 memb->origin=tr_new_name(json_string_value(json_array_get(prov, 0)));
839 tr_comm_memb_set_origin(memb, NULL);
843 void tr_comm_memb_add_to_provenance(TR_COMM_MEMB *memb, TR_NAME *hop)
845 if (memb->provenance==NULL) {
846 memb->provenance=json_array();
847 if (memb->provenance==NULL) {
848 tr_err("tr_comm_memb_add_to_provenance: unable to allocate provenance list.");
851 /* this is the first entry in the provenance, so it is the origin */
852 tr_comm_memb_set_origin(memb,tr_dup_name(hop));
853 if (memb->origin==NULL) {
854 tr_err("tr_comm_memb_add_to_provenance: unable to allocate origin.");
855 json_decref(memb->provenance);
856 memb->provenance=NULL;
860 if (0!=json_array_append_new(memb->provenance, tr_name_to_json_string(hop)))
861 tr_err("tr_comm_memb_add_to_provenance: unable to extend provenance list.");
864 size_t tr_comm_memb_provenance_len(TR_COMM_MEMB *memb)
866 if (memb->provenance==NULL)
868 return json_array_size(memb->provenance);
871 void tr_comm_memb_set_interval(TR_COMM_MEMB *memb, unsigned int interval)
873 memb->interval=interval;
876 unsigned int tr_comm_memb_get_interval(TR_COMM_MEMB *memb)
878 return memb->interval;
881 void tr_comm_memb_set_expiry(TR_COMM_MEMB *memb, struct timespec *time)
883 memb->expiry->tv_sec=time->tv_sec;
884 memb->expiry->tv_nsec=time->tv_nsec;
887 struct timespec *tr_comm_memb_get_expiry(TR_COMM_MEMB *memb)
892 int tr_comm_memb_is_expired(TR_COMM_MEMB *memb, struct timespec *curtime)
894 return ((curtime->tv_sec > memb->expiry->tv_sec)
895 || ((curtime->tv_sec == memb->expiry->tv_sec)
896 &&(curtime->tv_nsec >= memb->expiry->tv_nsec)));
899 TR_COMM_TABLE *tr_comm_table_new(TALLOC_CTX *mem_ctx)
901 TR_COMM_TABLE *ctab=talloc(mem_ctx, TR_COMM_TABLE);
904 ctab->memberships=NULL;
905 ctab->idp_realms=NULL;
906 ctab->rp_realms=NULL;
911 void tr_comm_table_free(TR_COMM_TABLE *ctab)
916 static TR_REALM_ROLE tr_comm_memb_role(TR_COMM_MEMB *memb)
923 return TR_ROLE_UNKNOWN;
926 void tr_comm_table_add_memb(TR_COMM_TABLE *ctab, TR_COMM_MEMB *new)
928 TR_COMM_MEMB *cur=NULL;
930 /* TODO: validate the member (must have valid comm and realm) */
932 /* handle the empty list case */
933 if (ctab->memberships==NULL) {
934 ctab->memberships=new;
935 talloc_steal(ctab, new);
939 /* The list was not empty. See if we already have a membership for this realm/comm/role */
940 switch (tr_comm_memb_role(new)) {
942 cur=tr_comm_table_find_rp_memb(ctab,
943 tr_rp_realm_get_id(tr_comm_memb_get_rp_realm(new)),
944 tr_comm_get_id(tr_comm_memb_get_comm(new)));
947 cur=tr_comm_table_find_idp_memb(ctab,
948 tr_idp_realm_get_id(tr_comm_memb_get_idp_realm(new)),
949 tr_comm_get_id(tr_comm_memb_get_comm(new)));
951 case TR_ROLE_UNKNOWN:
953 tr_err("tr_comm_table_add_memb: realm with unknown role added.");
958 /* no entry for this realm/comm/role, tack it on the end */
959 for (cur=ctab->memberships; cur->next!=NULL; cur=cur->next) { }
962 /* Found an entry. Add to the end of its same-origin list. */
963 while (cur->origin_next!=NULL) {
964 cur=cur->origin_next;
966 cur->origin_next=new;
969 talloc_steal(ctab, new);
972 /* Remove memb from ctab. Do not free anything. Do nothing if memb not in ctab. */
973 void tr_comm_table_remove_memb(TR_COMM_TABLE *ctab, TR_COMM_MEMB *memb)
975 TR_COMM_MEMB *cur=NULL; /* for walking the main list */
976 TR_COMM_MEMB *orig_cur=NULL; /* for walking the origin list */
978 if ((memb==NULL) || (ctab->memberships==NULL))
981 /* see if it's the first member */
982 if (ctab->memberships==memb) {
983 if (memb->origin_next!=NULL) {
984 memb->origin_next->next=ctab->memberships->next;
985 ctab->memberships=memb->origin_next;
987 ctab->memberships=memb->next;
992 /* see if it's in first member's origin list */
993 for (orig_cur=ctab->memberships->origin_next;
995 orig_cur=ctab->memberships->origin_next) {
996 if (orig_cur==memb) {
997 orig_cur->origin_next=memb->origin_next;
1002 /* now we have to walk the rest of the tree */
1003 for (cur=ctab->memberships; cur->next!=NULL; cur=cur->next) {
1004 if (cur->next==memb) {
1005 /* it matched an entry on the main list */
1006 if (memb->origin_next!=NULL) {
1007 /* replace the entry in the main list with the next element on the origin list */
1008 memb->origin_next->next=memb->next;
1009 cur->next=memb->origin_next;
1011 cur->next=memb->next; /* no origin list, just drop memb */
1014 /* it was not on the main list, walk the origin list */
1015 for (orig_cur=cur; orig_cur->next!=NULL; orig_cur=orig_cur->next) {
1016 if (orig_cur->next==memb) {
1017 orig_cur->next=memb->next;
1018 return; /* just drop the element from the origin list */
1025 static TR_NAME *tr_comm_memb_get_realm_id(TR_COMM_MEMB *memb)
1028 return tr_rp_realm_get_id(memb->rp);
1030 return tr_idp_realm_get_id(memb->idp);
1033 /* find a membership from any origin */
1034 TR_COMM_MEMB *tr_comm_table_find_memb(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm)
1036 TR_COMM_MEMB *cur=NULL;
1037 TR_NAME *cur_realm_name=NULL;
1039 for (cur=ctab->memberships; cur!=NULL; cur=cur->next) {
1040 cur_realm_name=tr_comm_memb_get_realm_id(cur);
1041 if (cur_realm_name==NULL) {
1042 tr_warning("tr_comm_table_find: encountered realm with no name.");
1045 if ((0==tr_name_cmp(realm, cur_realm_name)) &&
1046 (0==tr_name_cmp(comm, tr_comm_get_id(tr_comm_memb_get_comm(cur))))) {
1053 /* find a membership from a particular origin */
1054 TR_COMM_MEMB *tr_comm_table_find_memb_origin(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm, TR_NAME *origin)
1056 TR_NAME *cur_orig=NULL;
1057 TR_COMM_MEMB *cur=tr_comm_table_find_memb(ctab, realm, comm);
1059 return NULL; /* no match */
1061 /* had a match for comm/realm; find origin match */
1063 if (((origin==NULL) && (cur_orig==NULL)) ||
1064 ((origin!=NULL) && (cur_orig!=NULL) && (0==tr_name_cmp(origin, cur_orig))))
1065 return cur; /* found a match */
1066 cur=cur->origin_next;
1068 return NULL; /* no match */
1072 /* find an idp membership regardless of its origin */
1073 TR_COMM_MEMB *tr_comm_table_find_idp_memb(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm)
1075 TR_COMM_MEMB *cur=NULL;
1076 TR_IDP_REALM *idp_realm=NULL;
1078 for (cur=ctab->memberships; cur!=NULL; cur=cur->next) {
1079 idp_realm=tr_comm_memb_get_idp_realm(cur);
1080 if (idp_realm==NULL)
1081 continue; /* was not an idp */
1083 if ((0==tr_name_cmp(realm, idp_realm->realm_id)) &&
1084 (0==tr_name_cmp(comm, tr_comm_get_id(tr_comm_memb_get_comm(cur))))) {
1091 /* find an idp membership from a particular origin */
1092 TR_COMM_MEMB *tr_comm_table_find_idp_memb_origin(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm, TR_NAME *origin)
1094 TR_NAME *cur_orig=NULL;
1095 TR_COMM_MEMB *cur=tr_comm_table_find_idp_memb(ctab, realm, comm);
1097 return NULL; /* no match */
1099 /* had a match for comm/realm; find origin match */
1101 cur_orig=tr_comm_memb_get_origin(cur);
1102 if (((origin==NULL) && (cur_orig==NULL)) ||
1103 ((origin!=NULL) && (cur_orig!=NULL) && (0==tr_name_cmp(origin, cur_orig))))
1104 return cur; /* found a match */
1105 cur=cur->origin_next;
1107 return NULL; /* no match */
1110 /* find an rp membership from any origin */
1111 TR_COMM_MEMB *tr_comm_table_find_rp_memb(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm)
1113 TR_COMM_MEMB *cur=NULL;
1114 TR_RP_REALM *rp_realm=NULL;
1116 for (cur=ctab->memberships; cur!=NULL; cur=cur->next) {
1117 rp_realm=tr_comm_memb_get_rp_realm(cur);
1119 continue; /* was not an rp */
1121 if ((0==tr_name_cmp(realm, tr_rp_realm_get_id(rp_realm))) &&
1122 (0==tr_name_cmp(comm, tr_comm_get_id(tr_comm_memb_get_comm(cur))))) {
1129 /* find an rp membership from a particular origin */
1130 TR_COMM_MEMB *tr_comm_table_find_rp_memb_origin(TR_COMM_TABLE *ctab, TR_NAME *realm, TR_NAME *comm, TR_NAME *origin)
1132 TR_NAME *cur_orig=NULL;
1133 TR_COMM_MEMB *cur=tr_comm_table_find_rp_memb(ctab, realm, comm);
1135 return NULL; /* no match */
1137 /* had a match for comm/realm; find origin match */
1139 cur_orig=tr_comm_memb_get_origin(cur);
1140 if (((origin==NULL) && (cur_orig==NULL)) ||
1141 ((origin!=NULL) && (cur_orig!=NULL) && (0==tr_name_cmp(origin, cur_orig))))
1142 return cur; /* found a match */
1143 cur=cur->origin_next;
1145 return NULL; /* no match */
1148 TR_COMM *tr_comm_table_find_comm(TR_COMM_TABLE *ctab, TR_NAME *comm_id)
1150 return tr_comm_lookup(ctab->comms, comm_id);
1153 void tr_comm_table_add_comm(TR_COMM_TABLE *ctab, TR_COMM *new)
1155 tr_comm_add(ctab->comms, new);
1158 void tr_comm_table_remove_comm(TR_COMM_TABLE *ctab, TR_COMM *comm)
1160 tr_comm_remove(ctab->comms, comm);
1163 /* how many communities in the table? */
1164 size_t tr_comm_table_size(TR_COMM_TABLE *ctab)
1167 TR_COMM *this=ctab->comms;
1176 const char *tr_realm_role_to_str(TR_REALM_ROLE role)
1188 TR_REALM_ROLE tr_realm_role_from_str(const char *s)
1190 if (strcmp(s, "idp")==0)
1192 if (strcmp(s, "rp")==0)
1194 return TR_ROLE_UNKNOWN;