engine.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C), 2000-2003 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     if ( Run.init ) {
00126 
00127       sleep(1);
00128       kill_daemon(SIGTERM);
00129 
00130     }
00131     
00132   } else {
00133   
00134     initialize_service();
00135 
00136     if ( Run.httpdssl ) {
00137 
00138       mySSLServerConnection= init_ssl_server( Run.httpsslpem,
00139                           Run.httpsslclientpem );
00140 
00141       if ( mySSLServerConnection == NULL ) {
00142 
00143     error("http server: Could not initilize SSL engine\n");
00144     
00145     error("monit HTTP server not available\n");
00146 
00147     return;
00148       }
00149 
00150 #ifdef HAVE_OPENSSL
00151       mySSLServerConnection->server_socket= myServerSocket;
00152 #endif
00153     }
00154 
00155     while( !stopped ) {
00156       
00157       if ( NULL == (W= socket_producer(myServerSocket)) ) {
00158     
00159     continue;
00160 
00161       }
00162       
00163       if ( Run.httpdssl ) {
00164 
00165     if ( NULL == (W->ssl= 
00166               insert_accepted_ssl_socket(mySSLServerConnection) )) {
00167       
00168       error("http server: Cannot create SSL connection -- %s\n",
00169         STRERROR);
00170       destroy_wrapper(W);
00171 
00172       continue;
00173 
00174     }
00175 
00176     if (! embed_accepted_ssl_socket(W->ssl, W->socket)) {
00177 
00178       error("http server: Cannot establish SSL connection\n");
00179       destroy_wrapper(W);
00180 
00181       continue;
00182 
00183     }
00184     
00185       }
00186 
00187       if ( (!W->status) || (!authenticate(W)) ) {
00188     
00189     destroy_wrapper(W);
00190     
00191     continue;
00192     
00193       }
00194       
00195       if ( !Run.httpdssl ) {
00196     
00197     if ( !check_socket(W->socket) ) {
00198       
00199       error("http server: Client socket not ready -- %s\n", STRERROR);
00200       destroy_wrapper(W);
00201       
00202       continue;
00203       
00204     }
00205 
00206       }
00207 
00208       http_processor(W);
00209       
00210     }
00211 
00212   }
00213 
00214 }
00215 
00216 
00220 void stop_httpd() {
00221 
00222   stopped= TRUE;
00223   close_socket(myServerSocket);
00224   delete_ssl_server_socket(mySSLServerConnection);  
00225 
00226 }
00227 
00228 
00229 /* -------------------------------------------------------------- Properties */
00230 
00231 
00237 int add_host_allow(char *name) {
00238 
00239   struct hostent *hp;
00240 
00241   if ( ! (hp= gethostbyname(name)) ) {
00242     
00243     return FALSE;
00244     
00245   } else  {
00246     
00247     HostsAllow h= NEW(h);
00248     
00249     while(*hp->h_addr_list) {
00250 
00251       h->name= xstrdup( inet_ntoa( *(struct in_addr *) *hp->h_addr_list++) );
00252     
00253       LOCK(hostlist_mutex)
00254     
00255       if ( hostlist ) {
00256       
00257         HostsAllow p, n;
00258       
00259         for ( n= p= hostlist; p; n= p, p= p->next) {
00260     
00261       if ( !strcasecmp(p->name, name) ) {
00262       
00263         destroy_host_allow(h);
00264         goto done;
00265       
00266       }
00267     
00268         }
00269       
00270         n->next= h;
00271       
00272       } else {
00273       
00274         hostlist= h;
00275       
00276       }
00277 
00278       done:
00279       END_LOCK;
00280 
00281     }
00282 
00283   }
00284 
00285   return TRUE;
00286 
00287 }
00288 
00289 
00294 int has_hosts_allow() {
00295 
00296   int rv;
00297 
00298   LOCK(hostlist_mutex)
00299       rv= (hostlist != NULL );
00300   END_LOCK;
00301 
00302   return rv;
00303 
00304 }
00305 
00306 
00310 void destroy_hosts_allow() {
00311 
00312   if ( has_hosts_allow() ) {
00313     
00314     LOCK(hostlist_mutex)
00315     destroy_host_allow(hostlist);
00316         hostlist= NULL;
00317     END_LOCK;
00318     
00319   }
00320 
00321 }
00322 
00323 
00324 /* ----------------------------------------------------------------- Private */
00325 
00326 
00333 static void initialize_service() {
00334 
00335   init_service();
00336   check_Impl();
00337 
00338 }
00339 
00340 
00344 static void check_Impl() {
00345 
00346   if ( (Impl.doGet == 0) || (Impl.doPost == 0) ) {
00347     
00348     error("http server: Service Methods not implemented\n");
00349     _exit(1);
00350     
00351   }
00352   
00353 }
00354 
00355 
00362 static int authenticate(RequestWrapper w) {
00363 
00364   if ( is_host_allow(w->inetaddr->remote_host) ) {
00365     
00366     return TRUE;
00367     
00368   } 
00369 
00370   if ( ! has_hosts_allow() && Run.Auth.defined ) {
00371 
00372     return TRUE;
00373 
00374   }
00375   
00376   return FALSE;
00377 
00378 }
00379 
00380 
00381 
00386 static int is_host_allow(char *name) { 
00387 
00388   HostsAllow p;
00389   int rv= FALSE;
00390 
00391   LOCK(hostlist_mutex)
00392   
00393   for ( p= hostlist; p; p= p->next) {
00394 
00395     if ( !strncasecmp(p->name, name, STRLEN) ) {
00396       
00397       rv= TRUE;
00398       break;
00399       
00400     }
00401     
00402   }
00403 
00404   END_LOCK;
00405 
00406   return rv;
00407 
00408 }
00409 
00410 
00411 /* --------------------------------------------------------------- Factories */
00412 
00413 
00419 static RequestWrapper socket_producer(int server) {
00420 
00421   int client;
00422   int len= sizeof(struct sockaddr_in);
00423   struct sockaddr_in in;
00424 
00425   again:
00426   errno= 0;
00427   if ( (client= accept(server, (struct sockaddr*)&in, &len)) < 0) {
00428     
00429     if ( stopped ) {
00430       
00431       log("http server: service stopped\n");
00432       
00433     } else if ( errno == EINTR ) {
00434       
00435       goto again;
00436       
00437     } else {
00438       
00439       error("http server: cannot accept connection -- %s\n", STRERROR);
00440       
00441     }
00442     
00443     return NULL;
00444     
00445   }
00446 
00447   return create_wrapper(in.sin_addr, client);
00448 
00449 }
00450 
00451 
00459 static RequestWrapper create_wrapper(struct in_addr iaddr, int client) {
00460 
00461   RequestWrapper w= NEW(w);
00462   InetAddress i= NEW(i);
00463     
00464   i->remote_host= xstrdup( inet_ntoa(iaddr) );
00465   i->local_host= get_localhostname();
00466   w->inetaddr= i;
00467   w->socket= client;
00468   w->status= TRUE;
00469     
00470   return (w);
00471 
00472 }
00473 
00474 
00475 /* ----------------------------------------------------------------- Cleanup */
00476 
00477 
00481 static void destroy_host_allow(HostsAllow p) {
00482   
00483   HostsAllow a= p; 
00484   
00485   if ( a->next ) {
00486     
00487     destroy_host_allow(a->next);
00488     
00489   }
00490 
00491   free(a->name);
00492   free(a);
00493  
00494 }
00495