0c2a0c6e6d8442c60781a0a2d0dfe23556bb42fc
[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   if (idp==NULL)
131     return NULL;
132   
133   return idp->realm_id;
134 }
135
136 TR_NAME *tr_idp_realm_dup_id(TR_IDP_REALM *idp)
137 {
138   if (idp==NULL)
139     return NULL;
140   
141   return tr_dup_name(tr_idp_realm_get_id(idp));
142 }
143
144 void tr_idp_realm_set_id(TR_IDP_REALM *idp, TR_NAME *id)
145 {
146   if (idp->realm_id!=NULL)
147     tr_free_name(idp->realm_id);
148   idp->realm_id=id;
149 }
150
151 static TR_IDP_REALM *tr_idp_realm_tail(TR_IDP_REALM *idp)
152 {
153   if (idp==NULL)
154     return NULL;
155
156   while (idp->next!=NULL)
157     idp=idp->next;
158   return idp;
159 }
160
161 /* do not call directly, use the tr_idp_realm_add() macro */
162 TR_IDP_REALM *tr_idp_realm_add_func(TR_IDP_REALM *head, TR_IDP_REALM *new)
163 {
164   if (head==NULL)
165     head=new;
166   else {
167     tr_idp_realm_tail(head)->next=new;
168     while (new!=NULL) {
169       talloc_steal(head, new); /* put it in the right context */
170       new=new->next;
171     }
172   }
173   return head;
174 }
175
176 static int tr_idp_realm_apc_count(TR_IDP_REALM *idp)
177 {
178   int ii=0;
179   TR_APC *apc=idp->apcs;
180   while (apc!=NULL) {
181     apc=apc->next;
182     ii++;
183   }
184   return ii;
185 }
186
187 static int tr_idp_realm_aaa_server_count(TR_IDP_REALM *idp)
188 {
189   int ii=0;
190   TR_AAA_SERVER *aaa=idp->aaa_servers;
191   while (aaa!=NULL) {
192     aaa=aaa->next;
193     ii++;
194   }
195   return ii;
196 }
197
198 static char *tr_aaa_server_to_str(TALLOC_CTX *mem_ctx, TR_AAA_SERVER *aaa)
199 {
200   return talloc_strndup(mem_ctx, aaa->hostname->buf, aaa->hostname->len);
201 }
202
203 char *tr_idp_realm_to_str(TALLOC_CTX *mem_ctx, TR_IDP_REALM *idp)
204 {
205   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
206   char **s_aaa=NULL, *aaa_servers=NULL;
207   char **s_apc=NULL, *apcs=NULL;
208   int ii=0, aaa_servers_strlen=0, apcs_strlen=0;
209   int n_aaa_servers=tr_idp_realm_aaa_server_count(idp);
210   int n_apcs=tr_idp_realm_apc_count(idp);
211   TR_AAA_SERVER *aaa=NULL;
212   TR_APC *apc=NULL;
213   char *result=NULL;
214
215   /* get the AAA servers */
216   if (n_aaa_servers<=0)
217     aaa_servers=talloc_strdup(tmp_ctx, "");
218   else {
219     s_aaa=talloc_array(tmp_ctx, char *, n_aaa_servers);
220     for (aaa=idp->aaa_servers,ii=0; aaa!=NULL; aaa=aaa->next,ii++) {
221       s_aaa[ii]=tr_aaa_server_to_str(s_aaa, aaa);
222       aaa_servers_strlen+=strlen(s_aaa[ii]);
223     }
224
225     /* add space for comma-space separators */
226     aaa_servers_strlen+=2*(n_aaa_servers-1);
227
228     aaa_servers=talloc_array(tmp_ctx, char, aaa_servers_strlen+1);
229     aaa_servers[0]='\0';
230     for (ii=0; ii<n_aaa_servers; ii++) {
231       strcat(aaa_servers, s_aaa[ii]);
232       if (ii<(n_aaa_servers-1))
233         strcat(aaa_servers, ", ");
234     }
235     talloc_free(s_aaa);
236   }
237
238   /* get the APCs */
239   if (n_apcs<=0)
240     apcs=talloc_strdup(tmp_ctx, "");
241   else {
242     s_apc=talloc_array(tmp_ctx, char *, n_apcs);
243     for (apc=idp->apcs,ii=0; apc!=NULL; apc=apc->next,ii++) {
244       s_apc[ii]=tr_apc_to_str(s_apc, apc);
245       apcs_strlen+=strlen(s_apc[ii]);
246     }
247
248     /* add space for comma-space separators */
249     apcs_strlen+=2*(n_apcs-1);
250
251     apcs=talloc_array(tmp_ctx, char, apcs_strlen+1);
252     apcs[0]='\0';
253     for (ii=0; ii<n_apcs; ii++) {
254       strcat(apcs, s_apc[ii]);
255       if (ii<(n_apcs-1))
256         strcat(apcs, ", ");
257     }
258     talloc_free(s_apc);
259   }
260
261   result=talloc_asprintf(mem_ctx,
262                          "IDP realm: \"%.*s\"\n"
263                          "  shared: %s\n"
264                          "  local: %s\n"
265                          "  AAA servers: %s\n"
266                          "  APCs: %s\n",
267                          idp->realm_id->len, idp->realm_id->buf,
268                          (idp->shared_config)?"yes":"no",
269                          (idp->origin==TR_REALM_LOCAL)?"yes":"no",
270                          aaa_servers,
271                          apcs);
272   talloc_free(tmp_ctx);
273   return result;
274 }
275
276 void tr_idp_realm_incref(TR_IDP_REALM *realm)
277 {
278   realm->refcount++;
279 }
280
281 void tr_idp_realm_decref(TR_IDP_REALM *realm)
282 {
283   if (realm->refcount>0)
284     realm->refcount--;
285 }