mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
433 lines
12 KiB
C
433 lines
12 KiB
C
/*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
|
|
* *
|
|
* server.c... *
|
|
* *
|
|
* Function:..WorldWideWeb-X.500-Gateway - Server-Funktions *
|
|
* Based on web500gw.c 1.3 written by Frank Richter, TU Chemmniz *
|
|
* which is based on go500gw by Tim Howes, University of *
|
|
* Michigan - All rights reserved *
|
|
* *
|
|
* Authors:...Dr. Kurt Spanier & Bernhard Winkler, *
|
|
* Zentrum fuer Datenverarbeitung, Bereich Entwicklung *
|
|
* neuer Dienste, Universitaet Tuebingen, GERMANY *
|
|
* *
|
|
* ZZZZZ DDD V V *
|
|
* Creation date: Z D D V V *
|
|
* August 16 1995 Z D D V V *
|
|
* Last modification: Z D D V V *
|
|
* May 6 1999 ZZZZ DDD V *
|
|
* *
|
|
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/
|
|
|
|
/*
|
|
* $Id: server.c,v 1.6 1999/09/10 15:01:19 zrnsk01 Exp $
|
|
*
|
|
*/
|
|
|
|
#include "tgeneral.h"
|
|
#include "tglobal.h"
|
|
#include "init_exp.h"
|
|
#include "checkclient_exp.h"
|
|
#include "server.h"
|
|
#include "charray_exp.h"
|
|
|
|
#if defined( TUE_TEL ) || defined( AMBIXGW )
|
|
#include "tueTest_exp.h"
|
|
#endif
|
|
|
|
|
|
/**
|
|
** start_server()
|
|
**
|
|
** Start the Web-X.500-Server.
|
|
**/
|
|
|
|
PUBLIC void start_server(glob)
|
|
GLOB_STRUCT *glob;
|
|
{
|
|
|
|
int s, ns, rc;
|
|
int tblsize;
|
|
int pid = getpid();
|
|
fd_set readfds;
|
|
struct hostent *hp;
|
|
struct sockaddr_in from;
|
|
int fromlen;
|
|
void wait4child();
|
|
long int idx;
|
|
|
|
glob->stat_slice = time(&glob->stat_slice);
|
|
stat_slice = &glob->stat_slice;
|
|
/* if logging is desired via syslog establish connection to syslogd
|
|
and write first log-message */
|
|
if ( dosyslog ) {
|
|
|
|
openlog( glob->myname, LOG_PID | LOG_NOWAIT, dosyslog );
|
|
syslog( LOG_INFO, "initializing" );
|
|
|
|
}
|
|
|
|
/* set up the socket to listen on */
|
|
/* the actual port to listen is composed by the base-port
|
|
and the language-offset */
|
|
s = set_socket( glob->webport + atoi(glob->lang) );
|
|
|
|
/* arrange to reap children */
|
|
(void) signal( SIGCHLD, wait4child );
|
|
|
|
if ( dosyslog )
|
|
syslog (LOG_INFO, "socket: %d", s);
|
|
|
|
/* Read LDAP-filter for search-operations */
|
|
if ( (filtd = ldap_init_getfilter( glob->filterfile )) == NULL ) {
|
|
fprintf(stderr,"Cannot open filter file (%s)\n", glob->filterfile );
|
|
exit( 1 );
|
|
}
|
|
|
|
/* ### Code for the static server ### */
|
|
|
|
tblsize = getdtablesize();
|
|
syslog (LOG_INFO, "listening for calls...");
|
|
|
|
/* Initialisation of the Anti-Hack-code */
|
|
srand(pid);
|
|
if (glob->comrefuse) hackTimer();
|
|
bzero((char *) conArr, CARRSIZE * sizeof(int));
|
|
bzero((char *) shadowconArr, CARRSIZE * sizeof(long int));
|
|
bzero((char *) sumconArr, CARRSIZE * sizeof(long int));
|
|
|
|
#ifdef TUE_TEL
|
|
/* initialisation of dit_config 1st time */
|
|
if(glob->dit_config) {
|
|
init_dit_config();
|
|
}
|
|
#endif
|
|
|
|
/* initialisation of ip_refuse 1st time */
|
|
if(glob->ip_refuse) {
|
|
get_ip_refuse_clients(glob);
|
|
}
|
|
|
|
/* the server runs in an infinite loop !!! */
|
|
for ( ;; ) {
|
|
|
|
/* listen on the server-port for incoming connections */
|
|
FD_ZERO( &readfds );
|
|
FD_SET( s, &readfds );
|
|
|
|
if ((rc=select(tblsize,(fd_set *)&readfds,NULL,NULL,0))==-1) {
|
|
if ( debug ) perror( "select" );
|
|
continue;
|
|
} else if ( rc == 0 ) {
|
|
continue;
|
|
}
|
|
|
|
if ( ! FD_ISSET( s, &readfds ) )
|
|
continue;
|
|
|
|
|
|
/* got connection for the server: get data */
|
|
fromlen = sizeof(from);
|
|
|
|
/* increment the counter for total connections */
|
|
glob->svc_cnt++;
|
|
|
|
/* get new file-descriptors for the connection */
|
|
if ( (ns = accept( s, (struct sockaddr *) &from, &fromlen )) == -1 ) {
|
|
|
|
/* new fd could not be assigned -> log & bye */
|
|
if ( debug ) perror( "accept" );
|
|
if ( dosyslog ) {
|
|
syslog (LOG_INFO,
|
|
"problem with accept, errno=%d, %s <%08d>",
|
|
errno, strerror(errno), glob->svc_cnt);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
/* get time for performance log */
|
|
gettimeofday(×tore[0], NULL);
|
|
|
|
/* get client-address via DNS */
|
|
hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
|
|
sizeof(from.sin_addr.s_addr), AF_INET );
|
|
|
|
/* check ip-address for ip_refuse and bye if matched */
|
|
if ( check_ip_denial( &from, glob ) == NOTOK ) {
|
|
|
|
if ( dosyslog )
|
|
syslog( LOG_INFO, "IP-REFUSE: access denied for %s <%08d>",
|
|
inet_ntoa( from.sin_addr ), glob->svc_cnt);
|
|
|
|
close (ns);
|
|
continue;
|
|
|
|
}
|
|
|
|
/* get time for performance log */
|
|
gettimeofday(×tore[1], NULL);
|
|
|
|
/* Anti-Hack-part */
|
|
|
|
/* divide Host-IP-addresses in index-groups and count connection */
|
|
idx = IP_HACK(from.sin_addr.s_addr);
|
|
sumconArr[idx]++;
|
|
|
|
/* count try if already locked and bye */
|
|
if(conArr[idx] < 0) {
|
|
|
|
shadowconArr[idx]++;
|
|
close (ns);
|
|
continue;
|
|
|
|
}
|
|
|
|
/* if not yet locked and maximum amount of connections is exeeded ->
|
|
lock & message & bye
|
|
*/
|
|
if (glob->comrefuse && (++conArr[idx] > glob->comrefuse->maxAccept)){
|
|
|
|
if (dosyslog)
|
|
syslog(LOG_INFO,
|
|
"connection refused for %s (IDX=%d): %d attempts, %d cycles suspended <%08d>",
|
|
hp ? hp->h_name : "unknown", idx, conArr[idx],
|
|
glob->comrefuse->suspendCycle, glob->svc_cnt);
|
|
|
|
/* lock for x timecycles */
|
|
conArr[idx] = glob->comrefuse->suspendCycle;
|
|
|
|
/* bye, bye baby */
|
|
close (ns);
|
|
continue;
|
|
|
|
}
|
|
|
|
/* END of Anti-Hack-part */
|
|
|
|
/* Log the connection */
|
|
if ( dosyslog ) {
|
|
char msg[BUFSIZ];
|
|
|
|
sprintf(msg, "TCP connection from %s (%s,%u)",
|
|
(hp == NULL) ? "unknown" : hp->h_name,
|
|
inet_ntoa( from.sin_addr ), from.sin_port );
|
|
glob->server_connection_msg = strdup(msg);
|
|
}
|
|
|
|
if ( debug ) {
|
|
fprintf( stderr, "connection from %s (%s)\n",
|
|
(hp == NULL) ? "unknown" : hp->h_name,
|
|
inet_ntoa( from.sin_addr ) );
|
|
}
|
|
|
|
glob->unknown_host = !hp;
|
|
|
|
/* OK, now fork a sub-process performing the further communication
|
|
to the client; the father-process is listening for further
|
|
connections */
|
|
switch( pid = fork() ) {
|
|
case 0: /* child */
|
|
|
|
/* the connection to the client should last at most OUT_TIME
|
|
thereafter terminate connection */
|
|
signal(SIGALRM, timeoutf);
|
|
alarm(OUT_TIME);
|
|
|
|
/* the s-filedescriptor is not needed any more */
|
|
close( s );
|
|
|
|
/* Serve client-request */
|
|
do_queries( ns, glob , inet_ntoa( from.sin_addr ), from.sin_port, hp);
|
|
break;
|
|
|
|
case -1: /* failed */
|
|
if (dosyslog)
|
|
syslog (LOG_INFO, "%s <%08d>",
|
|
glob->server_connection_msg, glob->svc_cnt);
|
|
perror( "fork" );
|
|
break;
|
|
|
|
default: /* parent */
|
|
/* the father-process continues listening */
|
|
close( ns );
|
|
if ( debug )
|
|
fprintf( stderr, "forked child %d\n", pid );
|
|
break;
|
|
}
|
|
}
|
|
/* NOT REACHED */
|
|
}
|
|
/* end of function: start_server */
|
|
|
|
|
|
/**
|
|
** set_socket()
|
|
**
|
|
** Initialise socket to listen on and assign dedicated FD
|
|
**/
|
|
|
|
PRIVATE int set_socket(port)
|
|
int port;
|
|
{
|
|
int s, one;
|
|
struct sockaddr_in addr;
|
|
|
|
if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
|
|
perror( "socket" );
|
|
exit( 1 );
|
|
}
|
|
|
|
/* set option so clients can't keep us from coming back up */
|
|
one = 1;
|
|
if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
|
|
sizeof(one) ) < 0 ) {
|
|
perror( "setsockopt" );
|
|
exit( 1 );
|
|
}
|
|
|
|
/* bind to a name */
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_addr.s_addr = INADDR_ANY;
|
|
addr.sin_port = htons( port );
|
|
if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
|
|
perror( "bind" );
|
|
exit( 1 );
|
|
}
|
|
|
|
/* listen for connections */
|
|
if ( listen( s, 512 ) == -1 ) {
|
|
perror( "listen" );
|
|
exit( 1 );
|
|
}
|
|
|
|
if ( debug )
|
|
printf( "web500gw listening on port %d\n", port );
|
|
|
|
return( s );
|
|
}
|
|
/* end of function: set_socket */
|
|
|
|
/* If a sub-daemon exists, remove from Process list */
|
|
PRIVATE void wait4child(arg)
|
|
int arg;
|
|
{
|
|
int status;
|
|
|
|
if ( debug ) printf( "parent: catching child status\n" );
|
|
while ( wait3( &status, WNOHANG | WUNTRACED, 0 ) > 0 )
|
|
; /* NULL */
|
|
(void) signal( SIGCHLD, wait4child );
|
|
}
|
|
/* end of function: wait4child */
|
|
|
|
/* set signal-handler for Anti-Hack */
|
|
PRIVATE void hackTimer()
|
|
{
|
|
static time_t timer = (time_t) 0;
|
|
time_t now = time (&now);
|
|
|
|
/* re-read IP-REFUSE file if necessary */
|
|
re_readIPrefuse( globP );
|
|
|
|
/* re-read INDEX-URL file if necessary */
|
|
re_read_index_url_rules( globP );
|
|
|
|
if (!timer) {
|
|
|
|
timer = now + comRefuseP->statCycle;
|
|
|
|
}
|
|
|
|
signal(SIGALRM, reset_conMem);
|
|
alarm((rand() % comRefuseP->tdiff) + comRefuseP->tmin);
|
|
|
|
if (now + comRefuseP->tmin > timer) {
|
|
|
|
timer = put_hackStats (NULL, now) + comRefuseP->statCycle;
|
|
*stat_slice = now;
|
|
|
|
}
|
|
|
|
}
|
|
/* end of function: hackTimer */
|
|
|
|
|
|
/* Signal-handler for Anti-Hack-code */
|
|
PRIVATE void reset_conMem()
|
|
{
|
|
int i;
|
|
|
|
hackTimer();
|
|
|
|
for(i=0; i< 8192; i++)
|
|
if(conArr[i] >= 0) conArr[i] = 0;
|
|
else {
|
|
if(++conArr[i] == 0){
|
|
if (dosyslog)
|
|
syslog(LOG_INFO, "connection accept resumed for IDX=%d; \
|
|
%u connection attempts during suspension <%08d>", i, shadowconArr[i],
|
|
globP->svc_cnt);
|
|
shadowconArr[i] = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
/* end of function: reset_conMem */
|
|
|
|
|
|
/* regular output of the access-statistic */
|
|
PUBLIC time_t put_hackStats (fp, now)
|
|
FILE *fp;
|
|
time_t now;
|
|
{
|
|
int i, bereiche;
|
|
int is_html = (fp != NULL);
|
|
char *eol = is_html ? "<BR>\n" : "\n";
|
|
unsigned long int gesamt = 0;
|
|
|
|
if (!now) now = time (&now);
|
|
|
|
if (!fp) fp = fopen (comRefuseP->statFile, "w");
|
|
|
|
if (fp) {
|
|
|
|
if (is_html) fprintf (fp, "<PRE><BR>\n");
|
|
|
|
fprintf (fp, "Access-Statistic TWEB%s", eol);
|
|
fprintf (fp, "======================%s", eol);
|
|
if (comRefuseP) fprintf (fp, "FILE : %s%s", comRefuseP->statFile, eol);
|
|
fprintf (fp, "START: %s%s", format_time (*stat_slice), eol);
|
|
fprintf (fp, "END : %s%s%s%s", format_time (now), eol, eol, eol);
|
|
|
|
for (i = 0, bereiche = 0; i < CARRSIZE; i++) {
|
|
|
|
if(sumconArr[i]) {
|
|
fprintf (fp, "IP-IDX %5d: %8lu%s", i, sumconArr[i], eol);
|
|
gesamt += sumconArr[i];
|
|
bereiche++;
|
|
}
|
|
|
|
}
|
|
if(bereiche > 1) {
|
|
fprintf (fp, "----------------------%s", eol);
|
|
fprintf (fp, "Total: %8lu ( from %d IP-Ranges )%s",
|
|
gesamt, bereiche, eol);
|
|
}
|
|
|
|
if (is_html) {
|
|
|
|
fprintf (fp, "</PRE><BR>\n");
|
|
|
|
} else {
|
|
|
|
bzero((char *) sumconArr, CARRSIZE * sizeof(long int));
|
|
fprintf (fp, "\n");
|
|
fclose (fp);
|
|
|
|
}
|
|
}
|
|
|
|
return (now);
|
|
|
|
} /* put_hackStats */
|