/*
* The Spread Toolkit.
*
* The contents of this file are subject to the Spread Open-Source
* License, Version 1.0 (the ``License''); you may not use
* this file except in compliance with the License. You may obtain a
* copy of the License at:
*
* http://www.spread.org/license/
*
* or in the file ``license.txt'' found in this distribution.
*
* Software distributed under the License is distributed on an AS IS basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Creators of Spread are:
* Yair Amir, Michal Miskin-Amir, Jonathan Stanton.
*
* Copyright (C) 1993-2004 Spread Concepts LLC <spread@spreadconcepts.com>
*
* All Rights Reserved.
*
* Major Contributor(s):
* ---------------
* Cristina Nita-Rotaru crisn@cs.purdue.edu - group communication security.
* Theo Schlossnagle jesus@omniti.com - Perl, skiplists, autoconf.
* Dan Schoenblum dansch@cnds.jhu.edu - Java interface.
* John Schultz jschultz@cnds.jhu.edu - contribution to process group membership.
*
*/
/* Implements the functions required by the struct acm_hooks in a basic way
* that allows access depending on the IP address (or local unix socket)
* of the client.
*
* This works on an implicit DENY ALL, and only those ip's listed in the
* spread.access_ip file can connect.
*/
#include "arch.h"
#include "acm.h"
#include "session.h"
#include "sess_body.h" /* for Sessions[] */
#include "alarm.h"
#include <stdlib.h>
#include <string.h>
/* ACM callbacks */
void ip_auth_client_connection(struct session_auth_info *sess_auth_p);
void ip_auth_monitor_connection(mailbox mbox, int32 ip_addr);
/* internal utility functions */
static void insert_ip_rule(int32u net_address, int prefix);
static struct auth_ops IP_ops = {
ip_auth_client_connection,
ip_auth_monitor_connection,
NULL /* deliver_authinfo */
};
struct ip_rule {
int32u network_address;
int prefix_length;
struct ip_rule *next;
};
static struct ip_rule *Allow_Rules;
static bool IP_File_Loaded = FALSE;
void ip_init(void)
{
int32u localhost_ip, net_address;
char file_name[80];
FILE *fp;
int i1,i2,i3,i4, prefix;
char line[132];
char *ret;
int iret, i;
bool file_done = FALSE;
sprintf(file_name, "spread.access_ip");
if (!Acm_auth_add_method("IP", &IP_ops))
{
Alarmp( SPLOG_FATAL, ACM, "ip_init: Failed to register IP. Too many ACM methods registered. Recompile with larger limit.\n");
}
/* load spread.access_ip file */
if (NULL != (fp = fopen(file_name,"r")) )
Alarmp( SPLOG_INFO, ACM, "ip_init: using file: %s\n", file_name);
if (fp == NULL)
if (NULL != (fp = fopen(SPREAD_ETCDIR "/spread.access_ip", "r")) )
Alarmp( SPLOG_INFO, ACM, "ip_init: using file: " SPREAD_ETCDIR "/spread.access_ip\n");
if (fp == NULL)
{
Alarmp( SPLOG_ERROR, ACM, "ip_init: IP access control file not found.\nIf you are using IP based access controls, please make sure the file exists.\n");
IP_File_Loaded = FALSE;
return;
}
do{
ret = fgets(line,132,fp);
if (ret == NULL)
break;
if ( line[0] == '#')
continue;
if ( line[0] == 'u' && line[1] == 'n' && line[2] == 'i' && line[3] == 'x')
{
/* Special rule for unix domain sockets */
Alarmp( SPLOG_INFO, ACM, "ip_init: Allowing UNIX Domain Socket connections\n");
insert_ip_rule(0, 32);
continue;
}
if ( line[0] == 'l' && line[1] == 'o' && line[2] == 'c' && line[3] == 'a' && line[4] == 'l')
{
/* special rule for localhost connections over tcp */
Alarmp( SPLOG_INFO, ACM, "ip_init: Allowing localhost tcp Socket connections\n");
localhost_ip = 127 << 24;
insert_ip_rule(localhost_ip, 8);
continue;
}
for(i=0; i< 3; i++)
{
ret = strchr(line, '.' );
if ( ret == NULL)
{
Alarmp( SPLOG_ERROR, ACM, "ip_init: incomplete line: %s\n", line);
file_done = TRUE;
break;
}
*ret = ' ';
}
if (file_done) break;
iret = sscanf(line,"%d%d%d%d/%d",
&i1,&i2,&i3,&i4,&prefix);
if( iret == 4 ) prefix = 32;
else if( iret < 5 )
Alarmp( SPLOG_FATAL, ACM, "ip_init: not a valid ip network address/prefix line: %s\n", line);
Alarmp( SPLOG_INFO, ACM, "ip_init: network address %d.%d.%d.%d with prefix length: %d\n",
i1,i2,i3,i4, prefix);
net_address = ( (i1 << 24 ) | (i2 << 16) | (i3 << 8) | i4 );
insert_ip_rule(net_address, prefix);
} while(TRUE);
fclose(fp);
IP_File_Loaded = TRUE;
}
static void insert_ip_rule(int32u net_address, int prefix)
{
struct ip_rule *new_rule;
new_rule = malloc(sizeof(struct ip_rule));
if (!new_rule)
Alarmp(SPLOG_FATAL, ACM, "insert_ip_rule: Failed to allocate a struct ip_rule\n");
new_rule->network_address = net_address;
new_rule->prefix_length = prefix;
new_rule->next = NULL;
if (!Allow_Rules)
{
Allow_Rules = new_rule;
return;
}
new_rule->next = Allow_Rules;
Allow_Rules = new_rule;
}
void ip_auth_client_connection(struct session_auth_info *sess_auth_p)
{
int32u client_ip, client_net;
struct ip_rule *rule_p;
bool allowed;
int ses;
if (! IP_File_Loaded )
{
Alarmp( SPLOG_CRITICAL, ACM, "ip_open_connection: No spread.access_ip file loaded. NO connections will be allowed!\nYou probably don't want this!!\n");
Sess_session_report_auth_result( sess_auth_p, FALSE );
return;
}
ses = Sess_get_session_index (sess_auth_p->mbox);
client_ip = Sessions[ses].address;
rule_p = Allow_Rules;
allowed = FALSE;
/* Search allowed lists */
while(rule_p)
{
Alarmp(SPLOG_INFO, ACM, "ip_open_connection: client_ip: %d.%d.%d.%d, prefix: %d premask: 0x%x mask: 0x%x\n",
IP1(client_ip), IP2(client_ip), IP3(client_ip), IP4(client_ip), rule_p->prefix_length, ~0x0,
( (~0x0) << (32 - rule_p->prefix_length)) );
client_net = (client_ip & ( (~0x0) << (32 - rule_p->prefix_length)));
Alarmp(SPLOG_INFO, ACM, "ip_open_connection: comparing network %d.%d.%d.%d with client %d.%d.%d.%d\n",
IP1(rule_p->network_address), IP2(rule_p->network_address), IP3(rule_p->network_address),
IP4(rule_p->network_address), IP1(client_net),IP2(client_net),IP3(client_net),IP4(client_net) );
if (rule_p->network_address == client_net)
{
allowed = TRUE;
break;
}
rule_p = rule_p->next;
}
if (allowed)
Sess_session_report_auth_result( sess_auth_p, TRUE );
else
Sess_session_report_auth_result( sess_auth_p, FALSE );
}
void ip_auth_monitor_connection(mailbox mbox, int32 ip_addr)
{
/* Mon_Connection_Allowed(); */
}
syntax highlighted by Code2HTML, v. 0.9.1