6579253598f09126c775a0af240a57d8006834d7
[trust_router.git] / common / tr_idp.c
1 /*
2  * Copyright (c) 2012, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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.
32  *
33  */
34
35 #include <talloc.h>
36 #include <time.h>
37
38 #include <trust_router/tr_name.h>
39 #include <tr_idp.h>
40 #include <tr_config.h>
41
42 static int tr_aaa_server_destructor(void *obj)
43 {
44   TR_AAA_SERVER *aaa=talloc_get_type_abort(obj, TR_AAA_SERVER);
45   if (aaa->hostname!=NULL)
46     tr_free_name(aaa->hostname);
47   return 0;
48 }
49
50 TR_AAA_SERVER *tr_aaa_server_new(TALLOC_CTX *mem_ctx, TR_NAME *hostname)
51 {
52   TR_AAA_SERVER *aaa=talloc(mem_ctx, TR_AAA_SERVER);
53   if (aaa!=NULL) {
54     aaa->hostname=hostname;
55     talloc_set_destructor((void *)aaa, tr_aaa_server_destructor);
56   }
57   return aaa;
58 }
59
60 void tr_aaa_server_free(TR_AAA_SERVER *aaa)
61 {
62   talloc_free(aaa);
63 }
64
65 TR_AAA_SERVER *tr_idp_aaa_server_lookup(TR_IDP_REALM *idp_realms, TR_NAME *idp_realm_name, TR_NAME *comm)
66 {
67   TR_IDP_REALM *idp = NULL;
68
69   for (idp = idp_realms; idp != NULL; idp = idp->next) {
70     if (!tr_name_cmp(idp_realm_name, idp->realm_id)) {
71       /* TBD -- check that the community is one of the APCs for the IDP */
72       break;
73     }
74   }
75   if (idp)
76     return idp->aaa_servers;
77   else 
78     return NULL;
79 }
80
81 TR_AAA_SERVER *tr_default_server_lookup(TR_AAA_SERVER *default_servers, TR_NAME *comm)
82 {
83   if (!default_servers)
84     return NULL;
85
86   return(default_servers);
87 }
88
89 static int tr_idp_realm_destructor(void *obj)
90 {
91   TR_IDP_REALM *idp=talloc_get_type_abort(obj, TR_IDP_REALM);
92   if (idp->realm_id!=NULL)
93     tr_free_name(idp->realm_id);
94   return 0;
95 }
96
97 /* talloc note: lists of idp realms should be assembled using
98  * tr_idp_realm_add(). This will put all of the elements in the
99  * list, other than the head, as children of the head context.
100  * The head can then be placed in whatever context is desired. */
101 TR_IDP_REALM *tr_idp_realm_new(TALLOC_CTX *mem_ctx)
102 {
103   TR_IDP_REALM *idp=talloc(mem_ctx, TR_IDP_REALM);
104   if (idp!=NULL) {
105     idp->next=NULL;
106     idp->comm_next=NULL;
107     idp->realm_id=NULL;
108     idp->shared_config=0;
109     idp->aaa_servers=NULL;
110     idp->apcs=NULL;
111     idp->origin=TR_REALM_LOCAL;
112     idp->peer=NULL;
113     idp->expiry=talloc(idp, struct timespec);
114     if (idp->expiry==NULL) {
115       talloc_free(idp);
116       return NULL;
117     }
118     talloc_set_destructor((void *)idp, tr_idp_realm_destructor);
119   }
120   return idp;
121 }
122
123 void tr_idp_realm_free(TR_IDP_REALM *idp)
124 {
125   talloc_free(idp);
126 }
127
128 TR_NAME *tr_idp_realm_get_id(TR_IDP_REALM *idp)
129 {
130   return idp->realm_id;
131 }
132
133 void tr_idp_realm_set_id(TR_IDP_REALM *idp, TR_NAME *id)
134 {
135   if (idp->realm_id!=NULL)
136     tr_free_name(idp->realm_id);
137   idp->realm_id=id;
138 }
139
140 static TR_IDP_REALM *tr_idp_realm_tail(TR_IDP_REALM *idp)
141 {
142   if (idp==NULL)
143     return NULL;
144
145   while (idp->next!=NULL)
146     idp=idp->next;
147   return idp;
148 }
149
150 /* do not call directly, use the tr_idp_realm_add() macro */
151 TR_IDP_REALM *tr_idp_realm_add_func(TR_IDP_REALM *head, TR_IDP_REALM *new)
152 {
153   if (head==NULL)
154     head=new;
155   else {
156     tr_idp_realm_tail(head)->next=new;
157     while (new!=NULL) {
158       talloc_steal(head, new); /* put it in the right context */
159       new=new->next;
160     }
161   }
162   return head;
163 }
164
165 static int tr_idp_realm_apc_count(TR_IDP_REALM *idp)
166 {
167   int ii=0;
168   TR_APC *apc=idp->apcs;
169   while (apc!=NULL) {
170     apc=apc->next;
171     ii++;
172   }
173   return ii;
174 }
175
176 static int tr_idp_realm_aaa_server_count(TR_IDP_REALM *idp)
177 {
178   int ii=0;
179   TR_AAA_SERVER *aaa=idp->aaa_servers;
180   while (aaa!=NULL) {
181     aaa=aaa->next;
182     ii++;
183   }
184   return ii;
185 }
186
187 static char *tr_aaa_server_to_str(TALLOC_CTX *mem_ctx, TR_AAA_SERVER *aaa)
188 {
189   return talloc_strndup(mem_ctx, aaa->hostname->buf, aaa->hostname->len);
190 }
191
192 char *tr_idp_realm_to_str(TALLOC_CTX *mem_ctx, TR_IDP_REALM *idp)
193 {
194   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
195   char **s_aaa=NULL, *aaa_servers=NULL;
196   char **s_apc=NULL, *apcs=NULL;
197   int ii=0, aaa_servers_strlen=0, apcs_strlen=0;
198   int n_aaa_servers=tr_idp_realm_aaa_server_count(idp);
199   int n_apcs=tr_idp_realm_apc_count(idp);
200   TR_AAA_SERVER *aaa=NULL;
201   TR_APC *apc=NULL;
202   char *result=NULL;
203
204   /* get the AAA servers */
205   if (n_aaa_servers<=0)
206     aaa_servers=talloc_strdup(tmp_ctx, "");
207   else {
208     s_aaa=talloc_array(tmp_ctx, char *, n_aaa_servers);
209     for (aaa=idp->aaa_servers,ii=0; aaa!=NULL; aaa=aaa->next,ii++) {
210       s_aaa[ii]=tr_aaa_server_to_str(s_aaa, aaa);
211       aaa_servers_strlen+=strlen(s_aaa[ii]);
212     }
213
214     /* add space for comma-space separators */
215     aaa_servers_strlen+=2*(n_aaa_servers-1);
216
217     aaa_servers=talloc_array(tmp_ctx, char, aaa_servers_strlen+1);
218     aaa_servers[0]='\0';
219     for (ii=0; ii<n_aaa_servers; ii++) {
220       strcat(aaa_servers, s_aaa[ii]);
221       if (ii<(n_aaa_servers-1))
222         strcat(aaa_servers, ", ");
223     }
224     talloc_free(s_aaa);
225   }
226
227   /* get the APCs */
228   if (n_apcs<=0)
229     apcs=talloc_strdup(tmp_ctx, "");
230   else {
231     s_apc=talloc_array(tmp_ctx, char *, n_apcs);
232     for (apc=idp->apcs,ii=0; apc!=NULL; apc=apc->next,ii++) {
233       s_apc[ii]=tr_apc_to_str(s_apc, apc);
234       apcs_strlen+=strlen(s_apc[ii]);
235     }
236
237     /* add space for comma-space separators */
238     apcs_strlen+=2*(n_apcs-1);
239
240     apcs=talloc_array(tmp_ctx, char, apcs_strlen+1);
241     apcs[0]='\0';
242     for (ii=0; ii<n_apcs; ii++) {
243       strcat(apcs, s_apc[ii]);
244       if (ii<(n_apcs-1))
245         strcat(apcs, ", ");
246     }
247     talloc_free(s_apc);
248   }
249
250   result=talloc_asprintf(mem_ctx,
251                          "IDP realm: \"%.*s\"\n"
252                          "  shared: %s\n"
253                          "  local: %s\n"
254                          "  AAA servers: %s\n"
255                          "  APCs: %s\n",
256                          idp->realm_id->len, idp->realm_id->buf,
257                          (idp->shared_config)?"yes":"no",
258                          (idp->origin==TR_REALM_LOCAL)?"yes":"no",
259                          aaa_servers,
260                          apcs);
261   talloc_free(tmp_ctx);
262   return result;
263 }
264
265 void tr_idp_realm_incref(TR_IDP_REALM *realm)
266 {
267   realm->refcount++;
268 }
269
270 void tr_idp_realm_decref(TR_IDP_REALM *realm)
271 {
272   if (realm->refcount>0)
273     realm->refcount--;
274 }