diff -x CVS -ru monit.orig/gc.c monit/gc.c --- monit.orig/gc.c 2004-10-30 15:04:51.000000000 +0200 +++ monit/gc.c 2004-11-05 21:26:03.000000000 +0100 @@ -77,6 +77,7 @@ void gc() { destroy_hosts_allow(); + destroy_nets_allow(); gc_protocols(); diff -x CVS -ru monit.orig/http/cervlet.c monit/http/cervlet.c --- monit.orig/http/cervlet.c 2004-10-30 15:04:53.000000000 +0200 +++ monit/http/cervlet.c 2004-11-05 22:42:47.000000000 +0100 @@ -433,10 +433,10 @@ out_print(res, "httpd auth. style%s", - (Run.credentials!=NULL)&&has_hosts_allow()? - "Basic Authentication and Host allow list": + (Run.credentials!=NULL)&&(has_hosts_allow()||has_nets_allow())? + "Basic Authentication and Host/Net allow list": (Run.credentials!=NULL)?"Basic Authentication": - has_hosts_allow()?"Host allow list": + (has_hosts_allow()||has_nets_allow())?"Host/Net allow list": "No authentication"); print_alerts(res, Run.maillist); diff -x CVS -ru monit.orig/http/engine.c monit/http/engine.c --- monit.orig/http/engine.c 2004-10-30 15:04:53.000000000 +0200 +++ monit/http/engine.c 2004-11-05 23:22:58.000000000 +0100 @@ -66,6 +66,10 @@ #include #endif +#ifdef HAVE_CTYPE_H +#include +#endif + #ifdef HAVE_STRINGS_H #include #endif @@ -114,9 +118,11 @@ static int myServerSocket= 0; static HostsAllow hostlist= NULL; +static NetsAllow netlist= NULL; static volatile int stopped= FALSE; ssl_server_connection *mySSLServerConnection= NULL; static pthread_mutex_t hostlist_mutex= PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t netlist_mutex= PTHREAD_MUTEX_INITIALIZER; /* -------------------------------------------------------------- Prototypes */ @@ -124,9 +130,10 @@ static void check_Impl(); static void initialize_service(); -static int authenticate(const char*); -static int is_host_allow(const char *); +static int authenticate(const struct in_addr); +static int is_host_allow(const struct in_addr); static void destroy_host_allow(HostsAllow); +static void destroy_net_allow(NetsAllow); static Socket_T socket_producer(int, int, void*); @@ -307,6 +314,163 @@ } +int add_net_allow(char *s_network) { + + unsigned long network=0; + unsigned long mask=0; + char *temp=s_network; + char *longmask=NULL; + int shortmask=0; + int slashcount=0; + int dotcount=0; + int count=0; + NetsAllow h; + + struct in_addr inp; + + /* decide if we have xxx.xxx.xxx.xxx/yyy or + xxx.xxx.xxx.xxx/yyy.yyy.yyy.yyy */ + while (*temp!=0) { + if (*temp=='/') { + if ((slashcount==1) || (dotcount !=3)) { + + return FALSE; + + } + *temp=0; + temp++; + longmask=temp; + count=0; + slashcount=1; + dotcount=0; + } else if (*temp=='.') { + + dotcount++; + + } else if (!isdigit(*temp)) { + + return FALSE; + + } + + count++; + temp++; + } + + if ((dotcount==0) && (count > 1) && (count < 4)) { + + shortmask=atoi(longmask); + longmask=NULL; + + } else if (dotcount != 3) { + + return FALSE; + + } + + /* Parse the network */ + + if (inet_aton(s_network, &inp) == 0) { + + return FALSE; + + } + network=inp.s_addr; + + if (longmask==NULL) { + if ((shortmask > 32) || (shortmask < 0)) { + + return FALSE; + + } else if ( shortmask == 32 ) { + + mask=-1; + + } else { + + mask=(1<network=network; + h->mask=mask; + + LOCK(netlist_mutex) + + if(netlist) { + + NetsAllow p, n; + + for(n= p= netlist; p; n= p, p= p->next) { + + if((p->network == network) && ((p->mask == mask))) { + + destroy_net_allow(h); + goto done; + + } + + } + + n->next= h; + + } else { + + netlist= h; + + } + + done: + END_LOCK; + + return TRUE; +} + +/** + * Are any networks present in the net allow list? + * @return TRUE if the host allow list is non-empty, otherwise FALSE + */ +int has_nets_allow() { + + int rv; + + LOCK(netlist_mutex) + rv= (netlist != NULL); + END_LOCK; + + return rv; + +} + +/** + * Free the net allow list + */ +void destroy_nets_allow() { + + if(has_nets_allow()) { + + LOCK(netlist_mutex) + destroy_net_allow(netlist); + netlist= NULL; + END_LOCK; + + } + +} + /* ----------------------------------------------------------------- Private */ @@ -345,21 +509,22 @@ * FALSE. If allow Basic Authentication is defined in the Run.Auth * object, authentication is delegated to the processor module. */ -static int authenticate(const char *host) { +static int authenticate(const struct in_addr addr) { + + if(is_host_allow(addr)) { - if(is_host_allow(host)) { - return TRUE; } - if(! has_hosts_allow() && (Run.credentials!=NULL)) { + if(! has_hosts_allow() && ! has_nets_allow() && (Run.credentials!=NULL)) { return TRUE; } - log("%s: Denied connection from non-authorized client [%s]\n", prog, host); + log("%s: Denied connection from non-authorized client [%s]\n", prog, + inet_ntoa(addr)); return FALSE; @@ -370,17 +535,36 @@ * Returns TRUE if host is allowed to connect to * this server */ -static int is_host_allow(const char *name) { +static int is_host_allow(const struct in_addr addr) { HostsAllow p; + NetsAllow n; int rv= FALSE; LOCK(hostlist_mutex) for(p= hostlist; p; p= p->next) { - if(!strncasecmp(p->name, name, STRLEN)) { + if(!strncasecmp(p->name, inet_ntoa(addr), STRLEN)) { + + rv= TRUE; + break; + } + + } + + END_LOCK; + + if (rv) + return rv; + + LOCK(netlist_mutex) + + for(n= netlist; n; n= n->next) { + + if((n->network & n->mask) == (addr.s_addr & n->mask)) { + rv= TRUE; break; @@ -439,7 +623,7 @@ goto error; } - if(! authenticate(inet_ntoa(in.sin_addr))) { + if(! authenticate(in.sin_addr)) { goto error; } @@ -472,3 +656,18 @@ } +/** + * Free a (linked list of) net_allow ojbect(s). + */ +static void destroy_net_allow(NetsAllow p) { + + NetsAllow a= p; + + if(a->next) { + destroy_net_allow(a->next); + } + + FREE(a); + +} + diff -x CVS -ru monit.orig/http/engine.h monit/http/engine.h --- monit.orig/http/engine.h 2004-03-12 19:56:03.000000000 +0100 +++ monit/http/engine.h 2004-11-05 21:57:05.000000000 +0100 @@ -39,12 +39,22 @@ struct host_allow *next; } *HostsAllow; +typedef struct net_allow { + unsigned long network; + unsigned long mask; + /* For internal use */ + struct net_allow *next; +} *NetsAllow; + /* Public prototypes */ void start_httpd(int port, int backlog, char *bindAddr); void stop_httpd(); int add_host_allow(char *); +int add_net_allow(char *); int has_hosts_allow(); +int has_nets_allow(); void destroy_hosts_allow(); +void destroy_nets_allow(); #endif diff -x CVS -ru monit.orig/l.l monit/l.l --- monit.orig/l.l 2004-10-30 15:04:51.000000000 +0200 +++ monit/l.l 2004-11-05 21:55:03.000000000 +0100 @@ -232,6 +232,7 @@ recovered { return RECOVERED; } else { return ELSE; } collector { return COLLECTOR; } +net { return NET; } include { BEGIN(INCLUDE); } {byte} { return BYTE; } @@ -316,7 +317,7 @@ yylval.string= handle_quoted_string(yytext); save_arg(); return STRING; } - + \'[^\']*\' { steplinenobycr(yytext); yylval.string= handle_quoted_string(yytext); diff -x CVS -ru monit.orig/monit.pod monit/monit.pod --- monit.orig/monit.pod 2004-10-30 15:04:51.000000000 +0200 +++ monit/monit.pod 2004-11-05 23:18:00.000000000 +0100 @@ -1953,13 +1953,15 @@ validation). Both schema's can be used together or by itself. You B choose at least one. -=head4 Host allow list +=head4 Host and network allow list -The http server maintains an access-control list of hosts allowed -to connect to the server. You can add as many hosts as you want -to, but only hosts with a valid domain name or its IP address are -allowed. If you specify a hostname that does not resolve, monit -will write an error message in the console and not start. +The http server maintains an access-control list of hosts and +networks allowed to connect to the server. You can add as many +hosts as you want to, but only hosts with a valid domain name +or its IP address are allowed. If you specify a hostname that +does not resolve, monit will write an error message in the console +and not start. Networks require a network IP and a netmask to be +accepted. The http server will query a name server to check any hosts connecting to the server. If a host (client) is trying to connect @@ -1973,6 +1975,8 @@ allow localhost allow my.other.work.machine.com allow 10.1.1.1 + allow net 192.168.1.0/255.255.255.0 + allow 10.0.0.0/8 Clients, not mentioned in the allow list that tries to connect to the server are logged with their ip-address. diff -x CVS -ru monit.orig/p.y monit/p.y --- monit.orig/p.y 2004-10-30 15:04:51.000000000 +0200 +++ monit/p.y 2004-11-05 21:58:07.000000000 +0100 @@ -326,6 +326,7 @@ %token BYTE KILOBYTE MEGABYTE GIGABYTE %token INODE SPACE PERMISSION SIZE %token EXEC UNMONITOR ICMP ICMPECHO NONEXIST INVALID DATA RECOVERED +%token NET %left GREATER LESS EQUAL NOTEQUAL @@ -647,6 +648,11 @@ | ALLOW CRYPT PATH { htpasswd_file= $3; digesttype= DIGEST_CRYPT; } allowuserlist { FREE(htpasswd_file);} + | ALLOW NET STRING { ;if (! add_net_allow($3)) { + yyerror2("erroneous network identifier %s", $3); + } + FREE($3); + } | ALLOW STRING { if(!add_host_allow($2)) { yyerror2("hostname did not resolve",$2);