-const char jcc_rcs[] = "$Id: jcc.c,v 1.54 2001/11/07 00:03:14 steudten Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.65 2002/03/03 14:49:11 oes Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jcc.c,v $
*
* Revisions :
* $Log: jcc.c,v $
+ * Revision 1.65 2002/03/03 14:49:11 oes
+ * Fixed CLF logging: Now uses client's original HTTP request
+ *
+ * Revision 1.64 2002/03/03 09:18:03 joergs
+ * Made jumbjuster work on AmigaOS again.
+ *
+ * Revision 1.63 2002/03/02 04:14:50 david__schmidt
+ * Clean up a little CRLF unpleasantness that suddenly appeared
+ *
+ * Revision 1.62 2002/02/20 23:17:23 jongfoster
+ * Detecting some out-of memory conditions and exiting with a log message.
+ *
+ * Revision 1.61 2002/01/17 21:01:52 jongfoster
+ * Moving all our URL and URL pattern parsing code to urlmatch.c.
+ *
+ * Revision 1.60 2001/12/30 14:07:32 steudten
+ * - Add signal handling (unix)
+ * - Add SIGHUP handler (unix)
+ * - Add creation of pidfile (unix)
+ * - Add action 'top' in rc file (RH)
+ * - Add entry 'SIGNALS' to manpage
+ * - Add exit message to logfile (unix)
+ *
+ * Revision 1.59 2001/12/13 14:07:18 oes
+ * Fixed Bug: 503 error page now sent OK
+ *
+ * Revision 1.58 2001/11/30 23:37:24 jongfoster
+ * Renaming the Win32 config file to config.txt - this is almost the
+ * same as the corresponding UNIX name "config"
+ *
+ * Revision 1.57 2001/11/16 00:47:43 jongfoster
+ * Changing the tty-disconnection code to use setsid().
+ *
+ * Revision 1.56 2001/11/13 20:20:54 jongfoster
+ * Tabs->spaces, fixing a bug with missing {} around an if()
+ *
+ * Revision 1.55 2001/11/13 20:14:53 jongfoster
+ * Patch for FreeBSD setpgrp() as suggested by Alexander Lazic
+ *
* Revision 1.54 2001/11/07 00:03:14 steudten
* Give reliable return value if an error
* occurs not just 0 with new daemon mode.
#include "actions.h"
#include "cgi.h"
#include "loadcfg.h"
+#include "urlmatch.h"
const char jcc_h_rcs[] = JCC_H_VERSION;
const char project_h_rcs[] = PROJECT_H_VERSION;
"(copyright_or_otherwise)_applying_to_any_cookie._";
+#if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
+/*********************************************************************
+ *
+ * Function : SIG_handler
+ *
+ * Description : Signal handler for different signals.
+ * see man kill, signal ..
+ *
+ * Parameters :
+ * 1 : signal - the signal cause this function to call
+ *
+ * Returns : -
+ *
+ *********************************************************************/
+static void SIG_handler( int signal )
+{
+ switch( signal )
+ {
+ case SIGHUP:
+ log_error(LOG_LEVEL_INFO, "ignoring HUP signal (%d)", signal);
+ break;
+ case SIGTERM:
+ log_error(LOG_LEVEL_INFO, "exiting by signal %d .. bye", signal);
+
+#if defined(unix)
+ deletePidFile();
+#endif /* unix */
+
+ exit( signal );
+ break;
+
+ default:
+ /* want to exit jb so use FATAL */
+ log_error(LOG_LEVEL_FATAL, "SIG_handler: receive signal %d without handler.", signal);
+ }
+ return;
+}
+#endif
/*********************************************************************
*
* Function : chat
* Downgrade http version from 1.1 to 1.0 if +downgrade
* action applies
*/
- if (!strcmpic(http->ver, "HTTP/1.1") && csp->action->flags & ACTION_DOWNGRADE)
+ if ( (http->ssl == 0)
+ && (!strcmpic(http->ver, "HTTP/1.1"))
+ && (csp->action->flags & ACTION_DOWNGRADE))
{
freez(http->ver);
http->ver = strdup("HTTP/1.0");
+
+ if (http->ver == NULL)
+ {
+ log_error(LOG_LEVEL_FATAL, "Out of memory downgrading HTTP version");
+ }
+ }
+
+ /*
+ * Save a copy of the original request for logging
+ */
+ http->ocmd = strdup(http->cmd);
+
+ if (http->ocmd == NULL)
+ {
+ log_error(LOG_LEVEL_FATAL, "Out of memory copying HTTP request line");
}
/*
{
freez(http->cmd);
- http->cmd = strsav(http->cmd, http->gpc);
- http->cmd = strsav(http->cmd, " ");
+ http->cmd = strdup(http->gpc);
+ string_append(&http->cmd, " ");
if (fwd->forward_host)
{
- http->cmd = strsav(http->cmd, http->url);
+ string_append(&http->cmd, http->url);
}
else
{
- http->cmd = strsav(http->cmd, http->path);
+ string_append(&http->cmd, http->path);
}
- http->cmd = strsav(http->cmd, " ");
- http->cmd = strsav(http->cmd, http->ver);
+ string_append(&http->cmd, " ");
+ string_append(&http->cmd, http->ver);
+ if (http->cmd == NULL)
+ {
+ log_error(LOG_LEVEL_FATAL, "Out of memory rewiting SSL command");
+ }
}
enlist(csp->headers, http->cmd);
if (
/* a CGI call was detected and answered */
- (NULL != (rsp = dispatch_cgi(csp)))
+ (NULL != (rsp = dispatch_cgi(csp)))
/* or we are enabled and... */
|| (IS_ENABLED_AND (
/* ..the request was blocked */
- ( NULL != (rsp = block_url(csp)))
+ ( NULL != (rsp = block_url(csp)))
/* ..or untrusted */
#ifdef FEATURE_TRUST
/* ..or a fast redirect kicked in */
#ifdef FEATURE_FAST_REDIRECTS
|| (((csp->action->flags & ACTION_FAST_REDIRECTS) != 0) &&
- (NULL != (rsp = redirect_url(csp))))
+ (NULL != (rsp = redirect_url(csp))))
#endif /* def FEATURE_FAST_REDIRECTS */
- ))
- )
+ ))
+ )
{
/* Write the answer to the client */
if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length)
- || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
+ || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
{
log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
}
/* Log (FIXME: All intercept reasons apprear as "crunch" with Status 200) */
log_error(LOG_LEVEL_GPC, "%s%s crunch!", http->hostport, http->path);
- log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 3", csp->ip_addr_str, http->cmd);
+ log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 3", csp->ip_addr_str, http->ocmd);
/* Clean up and return */
free_http_response(rsp);
if (errno == EINVAL)
{
- rsp = error_response(csp, "no-such-domain", errno);
+ rsp = error_response(csp, "no-such-domain", errno);
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 404 0",
- csp->ip_addr_str, http->cmd);
+ csp->ip_addr_str, http->ocmd);
}
else
{
- rsp = error_response(csp, "connect-failed", errno);
+ rsp = error_response(csp, "connect-failed", errno);
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
- csp->ip_addr_str, http->cmd);
+ csp->ip_addr_str, http->ocmd);
}
+
/* Write the answer to the client */
if(rsp)
- {
+ {
if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length)
- || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
+ || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
{
log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
}
log_error(LOG_LEVEL_CONNECT, "OK");
hdr = sed(client_patterns, add_client_headers, csp);
+ if (hdr == NULL)
+ {
+ /* FIXME Should handle error properly */
+ log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
+ }
+
list_remove_all(csp->headers);
if (fwd->forward_host || (http->ssl == 0))
http->hostport);
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
- csp->ip_addr_str, http->cmd);
+ csp->ip_addr_str, http->ocmd);
rsp = error_response(csp, "connect-failed", errno);
if(rsp)
{
- if ((write_socket(csp->cfd, rsp->head, n) != n)
- || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
+ if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length)
+ || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
{
log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
}
* client, flush the rest, and get out of the way.
*/
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 2\n",
- csp->ip_addr_str, http->cmd);
+ csp->ip_addr_str, http->ocmd);
if (write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1) < 0)
{
log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
- csp->ip_addr_str, http->cmd);
+ csp->ip_addr_str, http->ocmd);
rsp = error_response(csp, "connect-failed", errno);
if(rsp)
{
if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length)
- || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
+ || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
{
log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
- }
- }
+ }
+ }
free_http_response(rsp);
return;
}
hdr = sed(server_patterns, add_server_headers, csp);
+ if (hdr == NULL)
+ {
+ /* FIXME Should handle error properly */
+ log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
+ }
+
n = strlen(hdr);
if ((write_socket(csp->cfd, hdr, n) != n)
log_error(LOG_LEVEL_ERROR, "Buffer size limit reached! Flushing and stepping back.");
hdr = sed(server_patterns, add_server_headers, csp);
+ if (hdr == NULL)
+ {
+ /* FIXME Should handle error properly */
+ log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
+ }
+
n = strlen(hdr);
byte_count += n;
*/
hdr = sed(server_patterns, add_server_headers, csp);
+ if (hdr == NULL)
+ {
+ /* FIXME Should handle error properly */
+ log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
+ }
+
n = strlen(hdr);
/* write the server's (modified) header to
}
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %d",
- csp->ip_addr_str, http->cmd, byte_count);
+ csp->ip_addr_str, http->ocmd, byte_count);
}
int main(int argc, const char *argv[])
#endif
{
- int argc_pos = 1;
+ int argc_pos = 1;
configfile =
-#ifdef AMIGA
- "AmiTCP:db/junkbuster/config"
-#elif !defined(_WIN32)
+#if !defined(_WIN32)
"config"
#else
- "junkbstr.txt"
+ "config.txt"
#endif
;
#ifdef _DEBUG
if ((argc >= 2) && (strcmp(argv[1], "-d")==0))
{
- ldebug++;
- argc_pos++;
- fprintf(stderr,"debugging enabled..\n");
+ ldebug++;
+ argc_pos++;
+ fprintf(stderr,"debugging enabled..\n");
}
#endif /* _DEBUG */
#endif /* !defined(_WIN32) || defined(_WIN_CONSOLE) */
}
#if defined(unix)
- if ( *configfile != '/' )
- {
- char *abs_file;
-
- DBG(1, ("configfile before '%s'\n",configfile) );
-
- /* make config-filename absolute here */
- if ( !(basedir = getcwd( NULL, 1024 )))
- {
- perror("get working dir failed");
- exit( 1 );
- }
- DBG(1, ("working dir '%s'\n",basedir) );
- if ( !(abs_file = malloc( strlen( basedir ) + strlen( configfile ) + 5 )))
- {
- perror("malloc failed");
- exit( 1 );
- }
- strcpy( abs_file, basedir );
- strcat( abs_file, "/" );
- strcat( abs_file, configfile );
- configfile = abs_file;
- DBG(1, ("configfile after '%s'\n",configfile) );
- }
+ if ( *configfile != '/' )
+ {
+ char *abs_file;
+
+ DBG(1, ("configfile before '%s'\n",configfile) );
+
+ /* make config-filename absolute here */
+ if ( !(basedir = getcwd( NULL, 1024 )))
+ {
+ perror("get working dir failed");
+ exit( 1 );
+ }
+ DBG(1, ("working dir '%s'\n",basedir) );
+ if ( !(abs_file = malloc( strlen( basedir ) + strlen( configfile ) + 5 )))
+ {
+ perror("malloc failed");
+ exit( 1 );
+ }
+ strcpy( abs_file, basedir );
+ strcat( abs_file, "/" );
+ strcat( abs_file, configfile );
+ configfile = abs_file;
+ DBG(1, ("configfile after '%s'\n",configfile) );
+ }
#endif /* defined unix */
#endif
-#if !defined(_WIN32) && !defined(__OS2__)
- signal(SIGPIPE, SIG_IGN);
- signal(SIGCHLD, SIG_IGN);
+#if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
+{
+ int sig;
+ struct sigaction action;
+
+ for ( sig = 1; sig < 16; sig++ )
+ {
+ switch( sig )
+ {
+ case 9:
+ case SIGPIPE:
+ case SIGCHLD:
+ case SIGHUP:
+ continue;
+ }
+ if ( signal(sig, SIG_handler) == SIG_ERR )
+ log_error(LOG_LEVEL_FATAL, "Can't set signal-handler for signal %d: %E", sig);
+ }
+ /* SIG_IGN */
+ if ( signal(SIGPIPE, SIG_IGN) == SIG_ERR )
+ log_error(LOG_LEVEL_FATAL, "Can't set SIG_IGN to SIGPIPE: %E");
+ if ( signal(SIGCHLD, SIG_IGN) == SIG_ERR )
+ log_error(LOG_LEVEL_FATAL, "Can't set SIG_IGN to SIGCHLD: %E");
+ /* log file reload */
+ if (!sigaction(SIGHUP,NULL,&action))
+ {
+ action.sa_handler = &SIG_handler;
+ action.sa_flags = SA_RESTART;
+
+ if ( sigaction(SIGHUP,&action,NULL))
+ log_error(LOG_LEVEL_FATAL, "Can't set signal-handler for signal SIGHUP: %E");
+ }
+ else
+ {
+ perror("sigaction");
+ log_error(LOG_LEVEL_FATAL, "Can't get sigaction data for signal SIGHUP");
+ }
+
+}
#else /* ifdef _WIN32 */
# ifdef _WIN_CONSOLE
#if defined(unix)
{
- pid_t pid = 0;
- int fd;
+ pid_t pid = 0;
+#if 0
+ int fd;
+#endif
- /*
- ** we make us a real daemon
- */
+ /*
+ * we make us a real daemon
+ */
#ifdef _DEBUG
- if ( !ldebug)
+ if ( !ldebug)
#endif
- pid = fork();
- if ( pid < 0 ) /* error */
- {
- perror("fork");
- exit( 3 );
- }
- else if ( pid != 0 ) /* parent */
- {
- int status;
- pid_t wpid;
- /*
- ** must check for errors
- ** child died due to missing files aso
- */
- sleep( 1 );
- wpid = waitpid( pid, &status, WNOHANG );
- if ( wpid != 0 )
- {
- exit( 1 );
- }
- exit( 0 );
- }
- /* child */
+ pid = fork();
+ if ( pid < 0 ) /* error */
+ {
+ perror("fork");
+ exit( 3 );
+ }
+ else if ( pid != 0 ) /* parent */
+ {
+ int status;
+ pid_t wpid;
+ /*
+ * must check for errors
+ * child died due to missing files aso
+ */
+ sleep( 1 );
+ wpid = waitpid( pid, &status, WNOHANG );
+ if ( wpid != 0 )
+ {
+ exit( 1 );
+ }
+ exit( 0 );
+ }
+ /* child */
+#if 1
+ /* Should be more portable, but not as well tested */
+ setsid();
+#else /* !1 */
#ifdef __FreeBSD__
setpgrp(0,0);
-#else
+#else /* ndef __FreeBSD__ */
setpgrp();
-#endif
- fd = open("/dev/tty", O_RDONLY);
- if ( fd )
- {
- /* no error check here */
- ioctl( fd, TIOCNOTTY,0 );
- close ( fd );
- }
- /* should close stderr (fd 2) here too, but the test for existence
- ** and load config file is done in listen_loop() and puts
- ** some messages on stderr there.
- */
+#endif /* ndef __FreeBSD__ */
+ fd = open("/dev/tty", O_RDONLY);
+ if ( fd )
+ {
+ /* no error check here */
+ ioctl( fd, TIOCNOTTY,0 );
+ close ( fd );
+ }
+#endif /* !1 */
+ /* should close stderr (fd 2) here too, but the test for existence
+ ** and load config file is done in listen_loop() and puts
+ ** some messages on stderr there.
+ */
#ifdef _DEBUG
- if ( !ldebug )
- close( 0 ); close( 1 );
+ if ( !ldebug )
+ {
+ close( 0 );
+ close( 1 );
+ }
#else
- close( 0 ); close( 1 );
+ close( 0 );
+ close( 1 );
#endif /* _DEBUG */
- chdir("/");
+ chdir("/");
+ writePidFile();
}
#endif /* defined unix */