1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
/*
* 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.access_ip", "r")) )
Alarmp( SPLOG_INFO, ACM, "ip_init: using file: ./spread.access_ip\n");
if (fp == NULL)
if (NULL != (fp = fopen("/etc/spread.access_ip", "r")) )
Alarmp( SPLOG_INFO, ACM, "ip_init: using file: /etc/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(); */
}
|