1 /*
2  * The Spread Toolkit.
3  *
4  * The contents of this file are subject to the Spread Open-Source
5  * License, Version 1.0 (the ``License''); you may not use
6  * this file except in compliance with the License.  You may obtain a
7  * copy of the License at:
8  *
9  * http://www.spread.org/license/
10  *
11  * or in the file ``license.txt'' found in this distribution.
12  *
13  * Software distributed under the License is distributed on an AS IS basis,
14  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15  * for the specific language governing rights and limitations under the
16  * License.
17  *
18  * The Creators of Spread are:
19  *  Yair Amir, Michal Miskin-Amir, Jonathan Stanton.
20  *
21  *  Copyright (C) 1993-2004 Spread Concepts LLC <spread@spreadconcepts.com>
22  *
23  *  All Rights Reserved.
24  *
25  * Major Contributor(s):
26  * ---------------
27  *    Cristina Nita-Rotaru crisn@cs.purdue.edu - group communication security.
28  *    Theo Schlossnagle    jesus@omniti.com - Perl, skiplists, autoconf.
29  *    Dan Schoenblum       dansch@cnds.jhu.edu - Java interface.
30  *    John Schultz         jschultz@cnds.jhu.edu - contribution to process group membership.
31  *
32  */
33 
34 
35 #include "arch.h"
36 #include <string.h>
37 #include <assert.h>
38 
39 #include "acm.h"
40 #include "alarm.h"
41 #include "memory.h"
42 #include "objects.h"
43 
44 struct auth_info {
45     char                name[MAX_AUTH_NAME];
46     bool                enabled;
47     bool                required;
48     struct auth_ops     ops;
49 };
50 
51 struct acp_info {
52     char                name[MAX_AUTH_NAME];
53     struct acp_ops      ops;
54 };
55 
56 static struct auth_info Auth_Methods[MAX_AUTH_METHODS];
57 static  int             Num_Auth_Methods;
58 
59 static struct acp_info  ACP_Methods[MAX_AUTH_METHODS];
60 static  int             Num_ACP_Methods;
61 
62 static  int             AccessControlPolicy;
63 
64 
acm_authname_to_type(char * auth_name)65 static int acm_authname_to_type(char *auth_name)
66 {
67     int i;
68     for ( i=0; i < Num_Auth_Methods; i++)
69     {
70         if (!strncmp(Auth_Methods[i].name, auth_name, MAX_AUTH_NAME))
71             return( i );
72     }
73     return(-1);
74 }
75 
acm_acpname_to_type(char * acp_name)76 static int acm_acpname_to_type(char *acp_name)
77 {
78     int i;
79     for ( i=0; i < Num_ACP_Methods; i++)
80     {
81         if (!strncmp(ACP_Methods[i].name, acp_name, MAX_AUTH_NAME))
82             return( i );
83     }
84     return(-1);
85 }
86 
Acm_init()87 void Acm_init()
88 {
89 	Mem_init_object( SESSION_AUTH_INFO, sizeof( struct session_auth_info ), 0, 0 );
90         /* establish default authentication -- allow all connections if nothing is configured.
91          * This is overridden by whatever is configured in the spread.conf file
92          */
93         Acm_auth_set_enabled("NULL");
94 
95         /* establish default policy if one is not configured */
96         if (!Acm_acp_set_policy("PERMIT"))
97                 Alarm(EXIT, "Acm_init: Unable to establish default PERMIT policy. Spread build is broken\n");
98 }
99 
Acm_auth_create_sess_info_forIP(mailbox mbox)100 struct session_auth_info *Acm_auth_create_sess_info_forIP(mailbox mbox)
101 {
102         struct session_auth_info *sess_auth_p;
103 
104         sess_auth_p = new( SESSION_AUTH_INFO );
105         if (sess_auth_p == NULL)
106         {
107                 Alarm( EXIT, "Acm_auth_create_sess_info_forIP: Failed to allocate an struct session_auth_info\n");
108                 return(NULL);
109         }
110 
111         sess_auth_p->mbox = mbox;
112         sess_auth_p->completed_required_auths = 0;
113         sess_auth_p->num_required_auths = 1;
114         sess_auth_p->required_auth_methods[0] = acm_authname_to_type("IP");
115         sess_auth_p->required_auth_results[0] = 0;
116 
117         return(sess_auth_p);
118 }
119 
Acm_auth_create_sess_info(mailbox mbox,char * auth_name)120 struct session_auth_info *Acm_auth_create_sess_info(mailbox mbox, char *auth_name)
121 {
122         int num_auths, i, j, type;
123         struct session_auth_info *sess_auth_p;
124         bool meth_registered;
125 
126         sess_auth_p = new( SESSION_AUTH_INFO );
127         if (sess_auth_p == NULL)
128         {
129                 Alarm( EXIT, "Acm_auth_create_sess_info: Failed to allocate an struct session_auth_info\n");
130                 return(NULL);
131         }
132 
133         sess_auth_p->mbox = mbox;
134         sess_auth_p->completed_required_auths = 0;
135 
136         num_auths = 0;
137         i = 0;
138         /* add methods client requested */
139         while( auth_name[i * MAX_AUTH_NAME] != '\0')
140         {
141                 type = acm_authname_to_type( &auth_name[i * MAX_AUTH_NAME]);
142                 if ( Auth_Methods[type].enabled )
143                 {
144                         sess_auth_p->required_auth_methods[num_auths] = type;
145                         num_auths++;
146                 }
147                 i++;
148         }
149         if (num_auths == 0 )
150         {
151                 Alarm( ACM, "Acm_auth_create_sess_info: Client on session mbox %d failed to request any valid methods: %s\n", mbox, auth_name);
152                 dispose(sess_auth_p);
153                 return(NULL);
154         }
155         /* Now add required methods that were not listed by client */
156         for ( i = 0; i < Num_Auth_Methods; i++)
157         {
158                 if ( Auth_Methods[i].required )
159                 {
160                         for (meth_registered = FALSE, j=0; j < num_auths; j++)
161                         {
162                                 if ( sess_auth_p->required_auth_methods[j] == i )
163                                         meth_registered = TRUE;
164                         }
165                         if ( ! meth_registered )
166                         {
167                                 sess_auth_p->required_auth_methods[num_auths] = i;
168                                 num_auths++;
169                         }
170                 }
171         }
172         if (num_auths == 0 )
173         {
174                 Alarm( ACM, "Acm_auth_create_sess_info: Failed to find any auth methods for session mbox %d which requested %s\n", mbox, auth_name);
175                 dispose(sess_auth_p);
176                 return(NULL);
177         }
178         sess_auth_p->num_required_auths = num_auths;
179         for (i=0; i< MAX_AUTH_METHODS; i++)
180         {
181                 sess_auth_p->required_auth_results[i] = 0;
182         }
183         return(sess_auth_p);
184 }
Acm_auth_set_enabled(char * auth_name)185 bool Acm_auth_set_enabled(char *auth_name)
186 {
187     int auth_type;
188     assert(auth_name != NULL);
189     auth_type = acm_authname_to_type(auth_name);
190     if (auth_type == -1)
191     {
192         Alarm( ACM, "Acm_auth_set_enabled: unknown auth name %s\n", auth_name);
193         return( FALSE );
194     }
195     Auth_Methods[auth_type].enabled = TRUE;
196     return( TRUE );
197 }
Acm_auth_set_disabled(char * auth_name)198 bool Acm_auth_set_disabled(char *auth_name)
199 {
200     int auth_type;
201     assert(auth_name != NULL);
202     auth_type = acm_authname_to_type(auth_name);
203     if (auth_type == -1)
204     {
205         Alarm( ACM, "Acm_auth_set_disabled: unknown auth name %s\n", auth_name);
206         return( FALSE );
207     }
208     Auth_Methods[auth_type].enabled = FALSE;
209     return( TRUE );
210 }
211 
Acm_auth_set_required(char * auth_name)212 bool Acm_auth_set_required(char *auth_name)
213 {
214     int auth_type;
215     assert(auth_name != NULL);
216     auth_type = acm_authname_to_type(auth_name);
217     if (auth_type == -1)
218     {
219         Alarm( ACM, "Acm_auth_set_required: unknown auth name %s\n", auth_name);
220         return( FALSE );
221     }
222     Auth_Methods[auth_type].required = TRUE;
223     return( TRUE );
224 }
225 
Acm_auth_add_method(char * name,struct auth_ops * ops)226 bool Acm_auth_add_method(char *name, struct auth_ops *ops)
227 {
228     assert(name != NULL);
229     assert(ops != NULL);
230 
231     if (Num_Auth_Methods == (MAX_AUTH_METHODS) )
232         return(FALSE);
233     memcpy(Auth_Methods[Num_Auth_Methods].name, name, MAX_AUTH_NAME);
234     Auth_Methods[Num_Auth_Methods].enabled = FALSE;
235     Auth_Methods[Num_Auth_Methods].required = FALSE;
236     Auth_Methods[Num_Auth_Methods].ops = *ops;
237 
238     Num_Auth_Methods++;
239     return(TRUE);
240 }
241 
Acm_auth_query_allowed(char * auth_name)242 bool Acm_auth_query_allowed(char *auth_name)
243 {
244     int auth_type;
245 
246     assert(auth_name != NULL);
247 
248     auth_type = acm_authname_to_type(auth_name);
249     if (auth_type == -1)
250     {
251         Alarm(ACM, "Acm_query_alloweds: unknown auth name %s\n", auth_name);
252         return(FALSE);
253     }
254     return(Auth_Methods[auth_type].enabled);
255 }
256 
Acm_auth_get_auth_client_connection_byname(char * auth_name)257 void *Acm_auth_get_auth_client_connection_byname(char *auth_name)
258 {
259     int auth_type;
260 
261     assert(auth_name != NULL);
262 
263     auth_type = acm_authname_to_type(auth_name);
264     if (auth_type == -1)
265     {
266         Alarm(ACM, "Acm_auth_get_auth_client_connection_byname: unknown auth name %s\n", auth_name);
267         return(FALSE);
268     }
269     return(Acm_auth_get_auth_client_connection(auth_type));
270 }
271 
Acm_auth_get_auth_client_connection(int authid)272 void *Acm_auth_get_auth_client_connection(int authid)
273 {
274     assert( authid >= 0 );
275     assert( authid < MAX_AUTH_METHODS );
276 
277     return(Auth_Methods[authid].ops.auth_client_connection);
278 }
279 
Acm_auth_get_allowed_list(void)280 char *Acm_auth_get_allowed_list(void)
281 {
282     int i;
283     static char list[MAX_AUTH_LIST_LEN];
284     char *c_ptr;
285 
286     c_ptr = list;
287     for ( i=0; i < Num_Auth_Methods; i++)
288     {
289         if (Auth_Methods[i].enabled)
290         {
291             sprintf(c_ptr, "%s ", Auth_Methods[i].name);
292             c_ptr += strlen(Auth_Methods[i].name);
293             c_ptr++; /* for space */
294         }
295     }
296     *c_ptr = 0; /* null terminate */
297     return(list);
298 }
299 
Acm_acp_add_method(char * name,struct acp_ops * ops)300 bool Acm_acp_add_method(char *name, struct acp_ops *ops)
301 {
302     assert(name != NULL);
303     assert(ops != NULL);
304 
305     if (Num_ACP_Methods == (MAX_AUTH_METHODS) )
306         return(FALSE);
307     memcpy(ACP_Methods[Num_ACP_Methods].name, name, MAX_AUTH_NAME);
308     ACP_Methods[Num_ACP_Methods].ops = *ops;
309 
310     Num_ACP_Methods++;
311     return(TRUE);
312 }
313 
Acm_acp_query_allowed(char * acp_name)314 bool Acm_acp_query_allowed(char *acp_name)
315 {
316     int acp_type;
317 
318     assert(acp_name != NULL);
319 
320     acp_type = acm_acpname_to_type(acp_name);
321     if (acp_type == -1)
322     {
323         Alarm(ACM, "Acm_acp_query_alloweds: unknown acp name %s\n", acp_name);
324         return(FALSE);
325     }
326     return(TRUE);
327 }
328 
Acm_acp_set_policy(char * policy_name)329 bool Acm_acp_set_policy(char *policy_name)
330 {
331     if (!Acm_acp_query_allowed(policy_name))
332         return(FALSE);
333     AccessControlPolicy = acm_acpname_to_type(policy_name);
334     return(TRUE);
335 }
336 
Acm_acp_fill_ops_byname(char * acp_name,struct acp_ops * acp_ops_h)337 bool Acm_acp_fill_ops_byname(char *acp_name, struct acp_ops *acp_ops_h)
338 {
339     int acp_type;
340 
341     assert(acp_name != NULL);
342     assert(acp_ops_h != NULL);
343 
344     acp_type = acm_acpname_to_type(acp_name);
345     if (acp_type == -1)
346     {
347         Alarm(ACM, "Acm_fill_acp_ops: unknown access control policy name %s\n", acp_name);
348         return(FALSE);
349     }
350     *acp_ops_h = ACP_Methods[acp_type].ops;
351     return(TRUE);
352 }
353 
Acm_acp_fill_ops(struct acp_ops * acp_ops_h)354 void Acm_acp_fill_ops(struct acp_ops *acp_ops_h)
355 {
356     assert(acp_ops_h != NULL);
357     assert( AccessControlPolicy >= 0 );
358     assert( AccessControlPolicy < Num_ACP_Methods );
359 
360     *acp_ops_h = ACP_Methods[AccessControlPolicy].ops;
361     return;
362 }
363