engine.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C), 2000-2002 by Contributors to the monit codebase. 
00003  * All Rights Reserved.
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License as
00007  * published by the Free Software Foundation; either version 2 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <errno.h>
00025 
00026 #ifdef HAVE_SYS_TYPES_H
00027 #include <sys/types.h>
00028 #endif
00029 
00030 #include <sys/socket.h>
00031 #include <time.h>
00032 
00033 #ifdef HAVE_NETDB_H
00034 #include <netdb.h>
00035 #endif
00036 
00037 #ifdef HAVE_UNISTD_H
00038 #include <unistd.h>
00039 #endif
00040 
00041 #ifdef HAVE_STRING_H
00042 #include <string.h>
00043 #endif
00044 
00045 #ifdef HAVE_NETINET_IN_H
00046 #include <netinet/in.h>
00047 #endif
00048 
00049 #ifdef HAVE_ARPA_INET_H
00050 #include <arpa/inet.h>
00051 #endif
00052 
00053 #include "http_utils.h" 
00054 #include "engine.h" 
00055 
00056 #define  HOST      1
00057 #define  WRAPPER   2
00058 #define  INETADDR  3
00059 
00060 /* Private variables */
00061 static int myServerSocket= 0;
00062 ssl_server_connection * mySSLServerConnection= NULL;
00063 static volatile int stopped= FALSE;
00064 static HostsAllow hostlist= NULL;
00065 static pthread_mutex_t hostlist_mutex= PTHREAD_MUTEX_INITIALIZER;
00066 
00067 /* Private prototypes */
00068 static void initialize_service();
00069 static void check_Impl();
00070 static int  authenticate(RequestWrapper);
00071 static int  is_host_allow(char *);
00072 static RequestWrapper socket_producer(int);
00073 static RequestWrapper create_wrapper(struct in_addr, int);
00074 static void destroy_host_allow(HostsAllow);
00075 
00102 /* ------------------------------------------------------------------ Public */
00103 
00104 
00111 void start_httpd(int port, int backlog, char *bindAddr) {
00112 
00113   RequestWrapper W;
00114 
00115   stopped= FALSE;
00116 
00117  
00118   if ( (myServerSocket= create_server_socket(port, backlog, bindAddr)) < 0 ) {
00119     
00120     error("http server: Could not create a server socket at port %d -- %s\n",
00121       port, STRERROR);
00122     
00123     error("monit HTTP server not available\n");
00124     
00125   } else {
00126   
00127     initialize_service();
00128 
00129     if ( Run.httpdssl ) {
00130 
00131       mySSLServerConnection= init_ssl_server( Run.httpsslpem,
00132                           Run.httpsslclientpem );
00133 
00134       if ( mySSLServerConnection == NULL ) {
00135 
00136     error("http server: Could not initilize SSL engine\n");
00137     
00138     error("monit HTTP server not available\n");
00139 
00140     return;
00141       }
00142 
00143 #ifdef HAVE_OPENSSL
00144       mySSLServerConnection->server_socket= myServerSocket;
00145 #endif
00146     }
00147 
00148     while( !stopped ) {
00149       
00150       if ( NULL == (W= socket_producer(myServerSocket)) ) {
00151     
00152     continue;
00153 
00154       }
00155       
00156       if ( Run.httpdssl ) {
00157 
00158     if ( NULL == (W->ssl= 
00159               insert_accepted_ssl_socket(mySSLServerConnection) )) {
00160       
00161       error("http server: Cannot create SSL connection -- %s\n",
00162         STRERROR);
00163       destroy_wrapper(W);
00164 
00165       continue;
00166 
00167     }
00168 
00169     if (! embed_accepted_ssl_socket(W->ssl, W->socket)) {
00170 
00171       error("http server: Cannot establish SSL connection\n");
00172       destroy_wrapper(W);
00173 
00174       continue;
00175 
00176     }
00177     
00178       }
00179 
00180       if ( (!W->status) || (!authenticate(W)) ) {
00181     
00182     destroy_wrapper(W);
00183     
00184     continue;
00185     
00186       }
00187       
00188       if ( !Run.httpdssl ) {
00189     
00190     if ( !check_socket(W->socket) ) {
00191       
00192       error("http server: Client socket not ready -- %s\n", STRERROR);
00193       destroy_wrapper(W);
00194       
00195       continue;
00196       
00197     }
00198 
00199       }
00200 
00201       http_processor(W);
00202       
00203     }
00204 
00205   }
00206 
00207 }
00208 
00209 
00213 void stop_httpd() {
00214 
00215   stopped= TRUE;
00216   close_socket(myServerSocket);
00217   delete_ssl_server_socket(mySSLServerConnection);  
00218 
00219 }
00220 
00221 
00222 /* -------------------------------------------------------------- Properties */
00223 
00224 
00230 int add_host_allow(char *name) {
00231 
00232   struct hostent *hp;
00233 
00234   if ( ! (hp= gethostbyname(name)) ) {
00235     
00236     return FALSE;
00237     
00238   } else  {
00239     
00240     HostsAllow h= NEW(h);
00241     
00242     while(*hp->h_addr_list) {
00243 
00244       h->name= xstrdup( inet_ntoa( *(struct in_addr *) *hp->h_addr_list++) );
00245     
00246       LOCK(hostlist_mutex)
00247     
00248       if ( hostlist ) {
00249       
00250         HostsAllow p, n;
00251       
00252         for ( n= p= hostlist; p; n= p, p= p->next) {
00253     
00254       if ( !strcasecmp(p->name, name) ) {
00255       
00256         destroy_host_allow(h);
00257         goto done;
00258       
00259       }
00260     
00261         }
00262       
00263         n->next= h;
00264       
00265       } else {
00266       
00267         hostlist= h;
00268       
00269       }
00270 
00271       done:
00272       END_LOCK;
00273 
00274     }
00275 
00276   }
00277 
00278   return TRUE;
00279 
00280 }
00281 
00282 
00287 int has_hosts_allow() {
00288 
00289   int rv;
00290 
00291   LOCK(hostlist_mutex)
00292       rv= (hostlist != NULL );
00293   END_LOCK;
00294 
00295   return rv;
00296 
00297 }
00298 
00299 
00303 void destroy_hosts_allow() {
00304 
00305   if ( has_hosts_allow() ) {
00306     
00307     LOCK(hostlist_mutex)
00308     destroy_host_allow(hostlist);
00309         hostlist= NULL;
00310     END_LOCK;
00311     
00312   }
00313 
00314 }
00315 
00316 
00317 /* ----------------------------------------------------------------- Private */
00318 
00319 
00326 static void initialize_service() {
00327 
00328   init_service();
00329   check_Impl();
00330 
00331 }
00332 
00333 
00337 static void check_Impl() {
00338 
00339   if ( (Impl.doGet == 0) || (Impl.doPost == 0) ) {
00340     
00341     error("http server: Service Methods not implemented\n");
00342     _exit(1);
00343     
00344   }
00345   
00346 }
00347 
00348 
00355 static int authenticate(RequestWrapper w) {
00356 
00357   if ( is_host_allow(w->inetaddr->remote_host) ) {
00358     
00359     return TRUE;
00360     
00361   } 
00362 
00363   if ( ! has_hosts_allow() && Run.Auth.defined ) {
00364 
00365     return TRUE;
00366 
00367   }
00368   
00369   return FALSE;
00370 
00371 }
00372 
00373 
00374 
00379 static int is_host_allow(char *name) { 
00380 
00381   HostsAllow p;
00382   int rv= FALSE;
00383 
00384   LOCK(hostlist_mutex)
00385   
00386   for ( p= hostlist; p; p= p->next) {
00387 
00388     if ( !strncasecmp(p->name, name, STRLEN) ) {
00389       
00390       rv= TRUE;
00391       break;
00392       
00393     }
00394     
00395   }
00396 
00397   END_LOCK;
00398 
00399   return rv;
00400 
00401 }
00402 
00403 
00404 /* --------------------------------------------------------------- Factories */
00405 
00406 
00412 static RequestWrapper socket_producer(int server) {
00413 
00414   int client;
00415   int len= sizeof(struct sockaddr_in);
00416   struct sockaddr_in in;
00417 
00418   again:
00419   errno= 0;
00420   if ( (client= accept(server, (struct sockaddr*)&in, &len)) < 0) {
00421     
00422     if ( stopped ) {
00423       
00424       log("http server: service stopped\n");
00425       
00426     } else if ( errno == EINTR ) {
00427       
00428       goto again;
00429       
00430     } else {
00431       
00432       error("http server: cannot accept connection -- %s\n", STRERROR);
00433       
00434     }
00435     
00436     return NULL;
00437     
00438   }
00439 
00440   return create_wrapper(in.sin_addr, client);
00441 
00442 }
00443 
00444 
00452 static RequestWrapper create_wrapper(struct in_addr iaddr, int client) {
00453 
00454   RequestWrapper w= NEW(w);
00455   InetAddress i= NEW(i);
00456     
00457   i->remote_host= xstrdup( inet_ntoa(iaddr) );
00458   i->local_host= get_localhostname();
00459   w->inetaddr= i;
00460   w->socket= client;
00461   w->status= TRUE;
00462     
00463   return (w);
00464 
00465 }
00466 
00467 
00468 /* ----------------------------------------------------------------- Cleanup */
00469 
00470 
00474 static void destroy_host_allow(HostsAllow p) {
00475   
00476   HostsAllow a= p; 
00477   
00478   if ( a->next ) {
00479     
00480     destroy_host_allow(a->next);
00481     
00482   }
00483 
00484   free(a->name);
00485   free(a);
00486  
00487 }
00488