79 |
#endif |
#endif |
80 |
|
|
81 |
#include "http_utils.h" |
#include "http_utils.h" |
82 |
#include "engine.h" |
#include "engine.h" |
83 |
|
#include "socket.h" |
84 |
|
|
|
#define HOST 1 |
|
|
#define WRAPPER 2 |
|
|
#define INETADDR 3 |
|
|
|
|
|
/* Private variables */ |
|
|
static int myServerSocket= 0; |
|
|
ssl_server_connection * mySSLServerConnection= NULL; |
|
|
static volatile int stopped= FALSE; |
|
|
static HostsAllow hostlist= NULL; |
|
|
static pthread_mutex_t hostlist_mutex= PTHREAD_MUTEX_INITIALIZER; |
|
|
|
|
|
/* Private prototypes */ |
|
|
static void initialize_service(); |
|
|
static void check_Impl(); |
|
|
static int authenticate(RequestWrapper); |
|
|
static int is_host_allow(char *); |
|
|
static RequestWrapper socket_producer(int); |
|
|
static RequestWrapper create_wrapper(struct in_addr, int); |
|
|
static void destroy_host_allow(HostsAllow); |
|
85 |
|
|
86 |
/** |
/** |
87 |
* A naive http 1.0 server. The server delegates handling of a HTTP |
* A naive http 1.0 server. The server delegates handling of a HTTP |
110 |
*/ |
*/ |
111 |
|
|
112 |
|
|
113 |
|
/* ------------------------------------------------------------- Definitions */ |
114 |
|
|
115 |
|
|
116 |
|
static int myServerSocket= 0; |
117 |
|
static HostsAllow hostlist= NULL; |
118 |
|
static volatile int stopped= FALSE; |
119 |
|
ssl_server_connection *mySSLServerConnection= NULL; |
120 |
|
static pthread_mutex_t hostlist_mutex= PTHREAD_MUTEX_INITIALIZER; |
121 |
|
|
122 |
|
|
123 |
|
/* -------------------------------------------------------------- Prototypes */ |
124 |
|
|
125 |
|
|
126 |
|
static void check_Impl(); |
127 |
|
static void initialize_service(); |
128 |
|
static int authenticate(Socket_T); |
129 |
|
static int is_host_allow(const char *); |
130 |
|
static void destroy_host_allow(HostsAllow); |
131 |
|
static Socket_T socket_producer(int, int, void*); |
132 |
|
|
133 |
|
|
134 |
/* ------------------------------------------------------------------ Public */ |
/* ------------------------------------------------------------------ Public */ |
135 |
|
|
136 |
|
|
142 |
*/ |
*/ |
143 |
void start_httpd(int port, int backlog, char *bindAddr) { |
void start_httpd(int port, int backlog, char *bindAddr) { |
144 |
|
|
145 |
RequestWrapper W; |
Socket_T S; |
146 |
|
|
147 |
stopped= Run.stopped; |
stopped= Run.stopped; |
148 |
|
|
149 |
if ( (myServerSocket= create_server_socket(port, backlog, bindAddr)) < 0 ) { |
if((myServerSocket= create_server_socket(port, backlog, bindAddr)) < 0) { |
150 |
|
|
151 |
log("http server: Could not create a server socket at port %d -- %s\n", |
log("http server: Could not create a server socket at port %d -- %s\n", |
152 |
port, STRERROR); |
port, STRERROR); |
153 |
|
|
154 |
log("monit HTTP server not available\n"); |
log("monit HTTP server not available\n"); |
155 |
|
|
156 |
if ( Run.init ) { |
if(Run.init) { |
157 |
|
|
158 |
sleep(1); |
sleep(1); |
159 |
kill_daemon(SIGTERM); |
kill_daemon(SIGTERM); |
160 |
|
|
161 |
} |
} |
162 |
|
|
163 |
} else { |
} else { |
164 |
|
|
165 |
initialize_service(); |
initialize_service(); |
166 |
|
|
167 |
if ( Run.httpdssl ) { |
if(Run.httpdssl) { |
168 |
|
|
169 |
mySSLServerConnection= init_ssl_server( Run.httpsslpem, |
mySSLServerConnection= init_ssl_server( Run.httpsslpem, |
170 |
Run.httpsslclientpem ); |
Run.httpsslclientpem); |
171 |
|
|
172 |
if ( mySSLServerConnection == NULL ) { |
if(mySSLServerConnection == NULL) { |
173 |
|
|
174 |
log("http server: Could not initilize SSL engine\n"); |
log("http server: Could not initilize SSL engine\n"); |
175 |
|
|
176 |
log("monit HTTP server not available\n"); |
log("monit HTTP server not available\n"); |
177 |
|
|
178 |
return; |
return; |
179 |
} |
} |
180 |
|
|
181 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
182 |
mySSLServerConnection->server_socket= myServerSocket; |
mySSLServerConnection->server_socket= myServerSocket; |
183 |
#endif |
#endif |
184 |
} |
} |
185 |
|
|
186 |
while( !stopped ) { |
while(! stopped) { |
187 |
|
|
188 |
if ( NULL == (W= socket_producer(myServerSocket)) ) { |
if(!(S= socket_producer(myServerSocket, port, mySSLServerConnection))) { |
|
|
|
189 |
continue; |
continue; |
|
|
|
|
} |
|
|
|
|
|
if ( Run.httpdssl ) { |
|
|
|
|
|
if ( NULL == (W->ssl= |
|
|
insert_accepted_ssl_socket(mySSLServerConnection) )) { |
|
|
|
|
|
log("http server: Cannot create SSL connection -- %s\n", |
|
|
STRERROR); |
|
|
destroy_wrapper(W); |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
if (! embed_accepted_ssl_socket(W->ssl, W->socket)) { |
|
|
|
|
|
log("http server: Cannot establish SSL connection\n"); |
|
|
destroy_wrapper(W); |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
190 |
} |
} |
191 |
|
|
192 |
if ( (!W->status) || (!authenticate(W)) ) { |
if(! authenticate(S)) { |
193 |
|
socket_free(&S); |
|
destroy_wrapper(W); |
|
|
|
|
194 |
continue; |
continue; |
|
|
|
|
} |
|
|
|
|
|
if ( !Run.httpdssl ) { |
|
|
|
|
|
if ( !check_socket(W->socket) ) { |
|
|
|
|
|
log("http server: Client socket not ready -- %s\n", STRERROR); |
|
|
destroy_wrapper(W); |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
195 |
} |
} |
196 |
|
|
197 |
http_processor(W); |
http_processor(S); |
198 |
|
|
199 |
} |
} |
200 |
|
|
201 |
close_socket(myServerSocket); |
if(S) { |
202 |
|
socket_free(&S); |
203 |
|
} |
204 |
delete_ssl_server_socket(mySSLServerConnection); |
delete_ssl_server_socket(mySSLServerConnection); |
205 |
|
|
|
pthread_exit(NULL); |
|
|
|
|
206 |
} |
} |
207 |
|
|
208 |
} |
} |
222 |
|
|
223 |
|
|
224 |
/** |
/** |
225 |
* Add hosts allowed to connect to this server. |
* Add hosts allowed to connect to this server. |
226 |
* @param name A hostname (A-Record) or IP address to be added to the hosts allow list |
* @param name A hostname (A-Record) or IP address to be added to the |
227 |
|
* hosts allow list |
228 |
* @return FALSE if the given host does not resolve, otherwise TRUE |
* @return FALSE if the given host does not resolve, otherwise TRUE |
229 |
*/ |
*/ |
230 |
int add_host_allow(char *name) { |
int add_host_allow(char *name) { |
231 |
|
|
232 |
struct hostent *hp; |
struct hostent *hp; |
233 |
|
|
234 |
if ( ! (hp= gethostbyname(name)) ) { |
if(! (hp= gethostbyname(name))) { |
235 |
|
|
236 |
return FALSE; |
return FALSE; |
237 |
|
|
243 |
|
|
244 |
while(*hp->h_addr_list) { |
while(*hp->h_addr_list) { |
245 |
|
|
246 |
h->name= xstrdup( inet_ntoa( *(struct in_addr *) *hp->h_addr_list++) ); |
h->name= xstrdup( inet_ntoa( *(struct in_addr *) *hp->h_addr_list++)); |
247 |
|
|
248 |
LOCK(hostlist_mutex) |
LOCK(hostlist_mutex) |
249 |
|
|
250 |
if ( hostlist ) { |
if(hostlist) { |
251 |
|
|
252 |
HostsAllow p, n; |
HostsAllow p, n; |
253 |
|
|
254 |
for ( n= p= hostlist; p; n= p, p= p->next) { |
for(n= p= hostlist; p; n= p, p= p->next) { |
255 |
|
|
256 |
if ( !strcasecmp(p->name, name) ) { |
if(!strcasecmp(p->name, name)) { |
257 |
|
|
258 |
destroy_host_allow(h); |
destroy_host_allow(h); |
259 |
goto done; |
goto done; |
291 |
int rv; |
int rv; |
292 |
|
|
293 |
LOCK(hostlist_mutex) |
LOCK(hostlist_mutex) |
294 |
rv= (hostlist != NULL ); |
rv= (hostlist != NULL); |
295 |
END_LOCK; |
END_LOCK; |
296 |
|
|
297 |
return rv; |
return rv; |
304 |
*/ |
*/ |
305 |
void destroy_hosts_allow() { |
void destroy_hosts_allow() { |
306 |
|
|
307 |
if ( has_hosts_allow() ) { |
if(has_hosts_allow()) { |
308 |
|
|
309 |
LOCK(hostlist_mutex) |
LOCK(hostlist_mutex) |
310 |
destroy_host_allow(hostlist); |
destroy_host_allow(hostlist); |
338 |
*/ |
*/ |
339 |
static void check_Impl() { |
static void check_Impl() { |
340 |
|
|
341 |
if ( (Impl.doGet == 0) || (Impl.doPost == 0) ) { |
if((Impl.doGet == 0) || (Impl.doPost == 0)) { |
342 |
|
|
343 |
log("http server: Service Methods not implemented\n"); |
log("http server: Service Methods not implemented\n"); |
344 |
_exit(1); |
_exit(1); |
349 |
|
|
350 |
|
|
351 |
/** |
/** |
352 |
* Returns TRUE if remote host is allowed to connect, if not shutdown |
* Returns TRUE if remote host is allowed to connect, otherwise return |
353 |
* the socket and return FALSE. If allow Basic Authentication is |
* FALSE. If allow Basic Authentication is defined in the Run.Auth |
354 |
* defined in the Run.Auth object, authentication is delegated to the |
* object, authentication is delegated to the processor module. |
|
* processor module. |
|
355 |
*/ |
*/ |
356 |
static int authenticate(RequestWrapper w) { |
static int authenticate(Socket_T S) { |
357 |
|
|
358 |
if ( is_host_allow(w->inetaddr->remote_host) ) { |
if(is_host_allow(socket_get_remote_host(S))) { |
359 |
|
|
360 |
return TRUE; |
return TRUE; |
361 |
|
|
362 |
} |
} |
363 |
|
|
364 |
if ( ! has_hosts_allow() && Run.Auth.defined ) { |
if(! has_hosts_allow() && Run.Auth.defined) { |
365 |
|
|
366 |
return TRUE; |
return TRUE; |
367 |
|
|
372 |
} |
} |
373 |
|
|
374 |
|
|
|
|
|
375 |
/** |
/** |
376 |
* Returns TRUE if host is allowed to connect to |
* Returns TRUE if host is allowed to connect to |
377 |
* this server |
* this server |
378 |
*/ |
*/ |
379 |
static int is_host_allow(char *name) { |
static int is_host_allow(const char *name) { |
380 |
|
|
381 |
HostsAllow p; |
HostsAllow p; |
382 |
int rv= FALSE; |
int rv= FALSE; |
383 |
|
|
384 |
LOCK(hostlist_mutex) |
LOCK(hostlist_mutex) |
385 |
|
|
386 |
for ( p= hostlist; p; p= p->next) { |
for(p= hostlist; p; p= p->next) { |
387 |
|
|
388 |
if ( !strncasecmp(p->name, name, STRLEN) ) { |
if(!strncasecmp(p->name, name, STRLEN)) { |
389 |
|
|
390 |
rv= TRUE; |
rv= TRUE; |
391 |
break; |
break; |
408 |
* Accept connections from Clients and create a RequestWraper object |
* Accept connections from Clients and create a RequestWraper object |
409 |
* for each successful accept. If accept fails, return a NULL object |
* for each successful accept. If accept fails, return a NULL object |
410 |
*/ |
*/ |
411 |
static RequestWrapper socket_producer(int server) { |
static Socket_T socket_producer(int server, int port, void *sslserver) { |
412 |
|
|
413 |
int client; |
int client; |
414 |
struct sockaddr_in in; |
struct sockaddr_in in; |
415 |
int len= sizeof(struct sockaddr_in); |
int len= sizeof(struct sockaddr_in); |
430 |
|
|
431 |
} else { |
} else { |
432 |
|
|
433 |
/* in the case that timeout or error occured, return NULL to allow |
/* If timeout or error occured, return NULL to allow the caller to |
434 |
* the caller handle various states (such as stopped) which can |
* handle various states (such as stopped) which can occure in the |
435 |
* occure in the meantime */ |
* meantime */ |
436 |
return NULL; |
return NULL; |
437 |
|
|
438 |
} |
} |
439 |
|
|
440 |
if(set_noblock(client) < 0) { |
if(set_noblock(client) < 0) { |
441 |
close_socket(client); |
goto error; |
|
return NULL; |
|
442 |
} |
} |
443 |
|
|
444 |
return create_wrapper(in.sin_addr, client); |
if(!check_socket(client)) { |
445 |
|
goto error; |
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
* Create a RequestWrapper. This function will always return a |
|
|
* RequestWraper. If the build is successful the status variable in |
|
|
* the Wrapper is set to TRUE otherwise it is set to FALSE. If the |
|
|
* build fails, the client socket is also shutdown. The build fails |
|
|
* if the connecting client does not have a valid domain name. |
|
|
*/ |
|
|
static RequestWrapper create_wrapper(struct in_addr iaddr, int client) { |
|
|
|
|
|
InetAddress i; |
|
|
RequestWrapper w; |
|
|
char localhost[STRLEN]; |
|
|
|
|
|
if(gethostname(localhost, sizeof(localhost)) < 0) { |
|
|
snprintf(localhost, STRLEN, "localhost"); |
|
446 |
} |
} |
447 |
|
|
448 |
|
|
449 |
|
return socket_create_a(client, inet_ntoa(in.sin_addr), port, sslserver); |
450 |
|
|
451 |
NEW(i); |
error: |
452 |
NEW(w); |
close_socket(client); |
453 |
w->inetaddr= i; |
|
454 |
w->status= TRUE; |
return NULL; |
|
w->socket= client; |
|
|
i->local_host= xstrdup(localhost); |
|
|
i->remote_host= xstrdup(inet_ntoa(iaddr)); |
|
|
|
|
|
return (w); |
|
455 |
|
|
456 |
} |
} |
457 |
|
|