fixes init script for non ipv6 enabled systems #472755
[packages/xinetd.git] / xinetd / access.c
1 /*
2  * (c) Copyright 1992 by Panagiotis Tsirigotis
3  * (c) Sections Copyright 1998-2001 by Rob Braun
4  * All rights reserved.  The file named COPYRIGHT specifies the terms 
5  * and conditions for redistribution.
6  */
7
8
9 #include "config.h"
10 #include <time.h>
11 #include <unistd.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <stdlib.h>
16
17 #ifdef HAVE_STDINT_H
18 #include <stdint.h>
19 #endif
20
21 #include "str.h"
22 #include "access.h"
23 #ifdef LIBWRAP
24 #include <tcpd.h>
25 #include <syslog.h>
26 int deny_severity = LOG_INFO;
27 int allow_severity = LOG_INFO;
28 #endif
29
30 #ifdef HAVE_LOADAVG
31 #include "xgetloadavg.h"
32 #endif
33
34 #include "msg.h"
35 #include "addr.h"
36 #include "sconf.h"
37 #include "log.h"        
38 #include "main.h"       /* for ps */
39 #include "sconst.h"
40 #include "sensor.h"
41 #include "state.h"
42 #include "timex.h"
43 #include "xconfig.h"
44 #include "xtimer.h"
45
46 #if !defined(NAME_MAX)
47       #ifdef FILENAME_MAX
48       #define NAME_MAX FILENAME_MAX
49       #else
50       #define NAME_MAX 256
51       #endif
52 #endif
53
54 const struct name_value access_code_names[] =
55 {
56    { "address",                  (int) AC_ADDRESS         },
57    { "time",                     (int) AC_TIME            },
58    { "fork",                     (int) AC_FORK            },
59    { "service_limit",            (int) AC_SERVICE_LIMIT   },
60    { "per_source_limit",         (int) AC_PER_SOURCE_LIMIT},
61    { "process_limit",            (int) AC_PROCESS_LIMIT   },
62    { "libwrap",                  (int) AC_LIBWRAP         },
63    { "load",                     (int) AC_LOAD            },
64    { "connections per second",   (int) AC_CPS             },
65    { CHAR_NULL,                  1                        },
66    { "UNKNOWN",                  0                        }
67 } ;
68
69
70 /* This is called by the flags processor */
71 static void cps_service_restart(void)
72 {
73    unsigned int i;
74    time_t nowtime;
75    const char *func = "cps_service_restart";
76
77    nowtime = time(NULL);
78    for( i=0; i < pset_count( SERVICES(ps) ); i++ ) {
79       struct service *sp;
80       struct service_config *scp;
81
82       sp = pset_pointer( SERVICES(ps), i);
83
84       if( SVC_STATE(sp) == SVC_DISABLED ) {
85          scp = SVC_CONF( sp );
86          if ( SC_TIME_REENABLE(scp) <= nowtime ) {
87             /* re-enable the service */
88             if( svc_activate(sp) == OK ) {
89                msg(LOG_ERR, func,
90                "Activating service %s", SC_NAME(scp));
91             } else {
92                msg(LOG_ERR, func,
93                "Error activating service %s", 
94                SC_NAME(scp)) ;
95             } /* else */
96          }
97       }
98    } /* for */
99 }
100
101
102 void cps_service_stop(struct service *sp, const char *reason)
103 {
104    struct service_config   *scp = SVC_CONF( sp ) ; 
105    time_t nowtime;
106
107    svc_deactivate( sp );
108    msg(LOG_ERR, "service_stop", 
109         "Deactivating service %s due to %s.  Restarting in %d seconds.", 
110         SC_NAME(scp), reason, (int)SC_TIME_WAIT(scp));
111    nowtime = time(NULL);
112    SC_TIME_REENABLE(scp) = nowtime + SC_TIME_WAIT(scp);
113    xtimer_add(cps_service_restart, SC_TIME_WAIT(scp));
114 }
115
116
117 /*
118  * Returns OK if the IP address in sinp is acceptable to the access control
119  * lists of the specified service.
120  */
121 static status_e remote_address_check(const struct service *sp, 
122                                      const union xsockaddr *sinp)
123 {
124    /*
125     * of means only_from, na means no_access
126     */
127    const char *func = "remote_addr_chk";
128    bool_int   of_matched  = FALSE;
129    bool_int   na_matched  = FALSE;
130
131    if (sinp == NULL )
132       return FAILED;
133
134    if ( SC_SENSOR( SVC_CONF(sp) ))
135    {   /* They hit a sensor...return FAILED since this isn't a real service */
136       process_sensor( sp, sinp ) ; 
137       return FAILED ;
138    } 
139    /* They hit a real server...note, this is likely to be a child process. */
140    else if ( check_sensor( sinp ) == FAILED )
141       return FAILED ;
142
143    /*
144     * The addrlist_match function returns an offset+1 to a matching
145     * entry in the supplied list. It is not a true/false answer.
146     */
147    if ( SC_NO_ACCESS( SVC_CONF(sp) ) != NULL )
148       na_matched = addrlist_match( SC_NO_ACCESS( SVC_CONF(sp) ), SA(sinp));
149
150    if ( SC_ONLY_FROM( SVC_CONF(sp) ) != NULL )
151       of_matched = addrlist_match( SC_ONLY_FROM( SVC_CONF(sp) ), SA(sinp));
152
153    /*
154     * Check if the specified address is in both lists
155     */
156    if ( na_matched && of_matched )
157    {
158       /*
159        * If there is a match in both lists, this is an error in the 
160        * service entry and we cannot allow a server to start.
161        * We do not disable the service entry (not our job).
162        */
163       msg( LOG_ERR, func,
164 "Service=%s: only_from list and no_access list match equally the address %s",
165             SVC_ID( sp ), 
166             xaddrname( sinp ) ) ;
167       return FAILED ;
168    }
169
170    /* A no_access list was specified and the socket is on it, fail */
171    if ( SC_NO_ACCESS( SVC_CONF(sp) ) != NULL && (na_matched != 0) )
172       return FAILED ;
173
174    /* A only_from list was specified and the socket wasn't on the list, fail */
175    if ( SC_ONLY_FROM( SVC_CONF(sp) ) != NULL && (of_matched == 0) )
176       return FAILED ;
177
178    /* If no lists were specified, the default is to allow starting a server */
179    return OK ;
180 }
181
182 /*
183  * mp is the mask pointer, t is the check type
184  */
185 #define CHECK( mp, t )      ( ( (mp) == NULL ) || M_IS_SET( *(mp), t ) )
186
187 /*
188  * Perform the access controls specified by check_mask.
189  * If check_mask is NULL, perform all access controls
190  */
191 access_e access_control( struct service *sp, 
192                          const connection_s *cp, 
193                          const mask_t *check_mask )
194 {
195    struct service_config   *scp = SVC_CONF( sp ) ;
196 #ifdef LIBWRAP
197    const char *func = "access_control";
198 #endif
199
200    /* make sure it's not one of the special pseudo services */
201    if( (strncmp(SC_NAME( scp ), INTERCEPT_SERVICE_NAME, sizeof(INTERCEPT_SERVICE_NAME)) == 0) || (strncmp(SC_NAME( scp ), LOG_SERVICE_NAME, sizeof(LOG_SERVICE_NAME)) == 0) ) {
202       return (AC_OK);
203    }
204
205    /* This has to be before the TCP_WRAPPERS stuff to make sure that
206       the sensor gets a chance to see the address */
207    if ( CHECK( check_mask, CF_ADDRESS ) &&
208          remote_address_check( sp, CONN_XADDRESS( cp ) ) == FAILED )
209       return( AC_ADDRESS ) ;
210
211    if( ! SC_NOLIBWRAP( scp ) ) 
212    { /* LIBWRAP code block */
213 #ifdef LIBWRAP
214       struct request_info req;
215       char *server = NULL;
216
217       /* get the server name to pass to libwrap */
218       if( SC_NAMEINARGS( scp ) )
219       {
220          if ( SC_SERVER_ARGV(scp) )
221             server = strrchr( SC_SERVER_ARGV(scp)[0], '/' );
222       }
223       else {
224          if( SC_SERVER(scp) == NULL ) {
225             /* probably an internal server, use the service id instead */
226             server = SC_ID(scp);
227             server--;  /* nasty.  we increment it later... */
228          } else {
229             server = strrchr( SC_SERVER(scp), '/' );
230          }
231       }
232
233       /* If this is a redirection or internal , go by the service name,
234        * since the server name will be bogus.
235        */
236       if( (SC_REDIR_ADDR(scp) != NULL) || (SC_IS_INTERNAL(scp) )) {
237          server = SC_NAME(scp);
238          server--; /* nasty but ok. */
239       }
240
241       if( server == NULL )
242       {
243          if ( SC_SERVER_ARGV(scp))
244             server = SC_SERVER_ARGV(scp)[0];
245       }
246       else
247          server++;
248
249       if ( scp->sc_libwrap != NULL )
250       {
251          server = SC_LIBWRAP(scp);
252       }
253
254       if ( server == NULL )
255       {
256          msg(deny_severity, func, 
257             "server param not provided to libwrap refusing connection to %s from %s", 
258             SC_ID(scp), conn_addrstr(cp));
259          return(AC_LIBWRAP);
260       }
261       request_init(&req, RQ_DAEMON, server, RQ_FILE, cp->co_descriptor, 0);
262       fromhost(&req);
263       if (!hosts_access(&req)) {
264          msg(deny_severity, func, 
265             "libwrap refused connection to %s (libwrap=%s) from %s",
266             SC_ID(scp), server, conn_addrstr(cp));
267          return(AC_LIBWRAP);
268       }
269 #endif
270    } /* LIBWRAP code block */
271
272    return( AC_OK ) ;
273 }
274
275
276 /* Do the "light weight" access control here */
277 access_e parent_access_control( struct service *sp, const connection_s *cp )
278 {
279    struct service_config *scp = SVC_CONF( sp ) ;
280    int n;
281    time_t nowtime;
282
283    /* make sure it's not one of the special pseudo services */
284    if( (strncmp(SC_NAME( scp ), INTERCEPT_SERVICE_NAME, sizeof(INTERCEPT_SERVICE_NAME)) == 0) || (strncmp(SC_NAME( scp ), LOG_SERVICE_NAME, sizeof(LOG_SERVICE_NAME)) == 0) ) 
285       return (AC_OK);
286
287    /* CPS handler */
288    if( SC_TIME_CONN_MAX(scp) != 0 ) {
289       int time_diff;
290       nowtime = time(NULL);
291       time_diff = nowtime - SC_TIME_LIMIT(scp) ;
292
293       if( SC_TIME_CONN(scp) == 0 ) {
294          SC_TIME_CONN(scp)++;
295          SC_TIME_LIMIT(scp) = nowtime;
296       } else if( time_diff < SC_TIME_CONN_MAX(scp) ) {
297          SC_TIME_CONN(scp)++;
298          if( time_diff == 0 ) time_diff = 1;
299          if( SC_TIME_CONN(scp)/time_diff > SC_TIME_CONN_MAX(scp) ) {
300             cps_service_stop(sp, "excessive incoming connections");
301             return(AC_CPS);
302          }
303       } else {
304          SC_TIME_LIMIT(scp) = nowtime;
305          SC_TIME_CONN(scp) = 1;
306       }
307    }
308
309 #ifdef HAVE_LOADAVG
310    if ( SC_MAX_LOAD(scp) != 0 ) {
311       if ( xgetloadavg() >= SC_MAX_LOAD(scp) ) {
312          msg(LOG_ERR, "xinetd", 
313             "refused connect from %s due to excessive load", 
314             conn_addrstr(cp));
315          return( AC_LOAD );
316       }
317    }
318 #endif
319
320    if ( SC_ACCESS_TIMES( scp ) != NULL && 
321          ! ti_current_time_check( SC_ACCESS_TIMES( scp ) ) )
322       return( AC_TIME ) ;
323
324    if ( SC_INSTANCES( scp ) != UNLIMITED &&
325         SVC_RUNNING_SERVERS( sp ) >= (unsigned)SC_INSTANCES( scp ) )
326       return( AC_SERVICE_LIMIT ) ;
327
328    if( SC_PER_SOURCE(scp) != UNLIMITED ) {
329       if ( CONN_XADDRESS(cp) != NULL ) {
330          unsigned int u ; 
331          n = 0 ;
332          for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ ) {
333             struct server *serp = NULL;
334             connection_s *cop = NULL;
335             serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
336             if ( (SERVER_SERVICE( serp ) == sp) &&
337                ( cop = SERVER_CONNECTION( serp ) ) ) {
338
339                if ( SC_IPV6( scp ) && 
340                  IN6_ARE_ADDR_EQUAL( &(cop->co_remote_address.sa_in6.sin6_addr),
341                    &((CONN_XADDRESS(cp))->sa_in6.sin6_addr)) )
342                   n++;
343                if ( SC_IPV4( scp ) && 
344                      (cop->co_remote_address.sa_in.sin_addr.s_addr == 
345                      (CONN_XADDRESS(cp))->sa_in.sin_addr.s_addr) )
346                   n++;
347             }
348          }
349
350          if ( n >= SC_PER_SOURCE(scp) )
351             return( AC_PER_SOURCE_LIMIT ) ;
352       }
353    }
354
355    if ( ps.ros.process_limit ) {
356       unsigned processes_to_create = SC_IS_INTERCEPTED( scp ) ? 2 : 1 ;
357
358       if ( pset_count( SERVERS( ps ) ) + processes_to_create > 
359          ps.ros.process_limit ) {
360          return( AC_PROCESS_LIMIT ) ;
361       }
362    }
363
364    return (AC_OK);
365 }
366